Synergex.SynergyDE.IOExtensions.IOHooks

WTSupported in traditional Synergy on Windows
WNSupported in Synergy .NET on Windows
USupported on UNIX
VSupported on OpenVMS
namespace Synergex.SynergyDE.IOExtensions
class IOHooks
    protected readonly channel,                 int
    protected syserr,                           int
    protected sysstv,                           int

The IOHooks class makes it possible to perform custom I/O without changing any code in your existing I/O routines. Unlike the other system‑supplied classes, you don’t call the hook routines yourself. Instead, IOHooks provides 4 constructors and 17 pre‑ and post‑operation virtual hook methods that (if implemented) are called automatically. (See Pre‑operation hook methods and Post‑operation hook methods.) Your implementation of these methods must exactly match the method signature you’re overriding; otherwise, you’ll get a “No suitable Method found to override” error (NOOVR) when compiling. You can extend these methods to implement dynamic operation logging, perform pre‑ or post‑I/O processing in your application, or whatever else you need them to do.

The class that you create by extending the IOHooks base class must implement at least one constructor and override at least one hook method, depending on which I/O operations you need. In your application itself, you’ll create an instance of your class and register it as a file I/O event handler for a channel or Select statement.

For example, if you want to perform some processing before and after a READS operation, you’ll override the READS pre‑ and post‑operation hook methods. Your custom pre‑operation method will then be executed before any READS occurs. The READS itself is issued as soon as your method exits, followed immediately by your post‑operation hook method. Upon exit of the post‑operation hook method, your application resumes.

Constructors

IOHooks

public IOHooks(channel)

Creates or replaces a new instance of the I/O event handler class associated with the specified channel opened to a file (n).

or

public IOHooks(Select.From)

Creates or replaces a new instance of the I/O event handler class associated with a file referenced in a From object.

or

public IOHooks(channel, premask, postmask)

Creates or replaces a new instance of the I/O event handler class associated with the specified chanel opened to a file (n) and two bit masks (IOEventMask).

or

method IOHooks(Select.From, premask, postmask)

Creates or replaces a new instance of the I/O event handler class associated with a file referenced in a From object and two bit masks (IOEventMask).

Methods

IOHooks.IOReset

public IOReset(premask, postmask), void

Dynamically changes hook methods that are to be used in an existing event handler instance. See the Discussion.

premask

The pre‑operation hook routines to be used. (IOEventMask)

postmask

The post‑operation hook routines to be used. (IOEventMask)

Pre‑operation hook methods

find_pre_operation_hook

public virtual method find_pre_operation_hook, void
    mismatch in optional key, n
    in optional in_rfa,       a
    in optional keynum,       n
    in flags,                 IOFlags
proc
.
.
.
endmethod

If implemented, called before a FIND operation.

key

(optional) Key value passed to the FIND. (MISMATCH n)

in_rfa

(optional) Incoming RFA/GRFA via the RFA qualifier. (a)

keynum

(optional) Numeric KEYNUM value. (n)

flags

Set to any IOFlags present. (IOFlags)

read_pre_operation_hook

public virtual method read_pre_operation_hook, void
    mismatch in optional key,  n
    in optional in_rfa,        a
    in optional keynum,        n
    in flags,                  IOFlags
proc
.
.
.
endmethod

If implemented, called before a READ operation.

key

(optional) Key value passed to the READ. (MISMATCH n)

in_rfa

(optional) Incoming RFA/GRFA via the RFA qualifier. (a)

keynum

(optional) Numeric KEYNUM value. (n)

flags

Set to any IOFlags present. (IOFlags)

reads_pre_operation_hook

public virtual method reads_pre_operation_hook, void
    in flags,      IOFlags
proc
.
.
.
endmethod

If implemented, called before a READS operation.

flags

Set to any IOFlags present. (IOFlags)

write_pre_operation_hook

public virtual method write_pre_operation_hook, void
    inout buffer,              a
    in optional recnum,        n
    in optional in_rfa,        a
    in flags,                  IOFlags
proc
.
.
.
endmethod

If implemented, called before a WRITE operation (or AlphaEnumerator.Current set property or AlphaEnumerator.SparseUpdate when using Select).

buffer

Record to be written. (a)

recnum

(optional) Alphanumeric record number to be written (non‑ISAM) or not ^PASSED (ISAM). (n)

in_rfa

(optional) Incoming RFA/GRFA via the RFA qualifier. (a)

flags

Set to any IOFlags present. (IOFlags)

writes_pre_operation_hook

public virtual method writes_pre_operation_hook, void
    inout buffer,              a
    in flags,                  IOFlags
proc
.
.
.
endmethod

If implemented, called before a WRITES operation.

buffer

Record to be written. (a)

flags

Set to any IOFlags present. (IOFlags)

store_pre_operation_hook

public virtual method store_pre_operation_hook, void
    inout buffer,          a
    in flags,              IOFlags
proc
.
.
.
endmethod

If implemented, called before a STORE operation.

buffer

Record to be written. (a)

flags

Set to any IOFlags present. (IOFlags)

delete_pre_operation_hook

public virtual method delete_pre_operation_hook, void
proc
.
.
.
endmethod

If implemented, called before a DELETE operation (or the AlphaEnumerator.DeleteCurrent() or RestrictedAlphaEnumerator.DeleteCurrent() method when using Select).

unlock_pre_operation_hook

public virtual method unlock_pre_operation_hook, void
    in optional rfa,                    a
    in flags,                           IOFlags
proc
.
.
.
endmethod

If implemented, called before an UNLOCK operation.

rfa

(optional) Incoming RFA/GRFA if ^MATCH:RFA and RFA qualifiers were specified. (a)

flags

Set to any IOFlags present. (IOFlags)

close_pre_operation_hook

public virtual method close_pre_operation_hook, void
    in flags,                   IOFlags
proc
.
.
.
endmethod

If implemented, called before a CLOSE operation.

flags

Set to any IOFlags present. (IOFlags)

Close_pre_operation_hook() is called only when a CLOSE statement is explicitly called (in traditional Synergy only) on normal program termination or an explicit STOP statement. Under abnormal termination (an unhandled exception or untrapped error), the close_pre_operation_hook() method will not be called. Therefore, if you want to rely on close_pre_operation_hook() always being called, but you haven’t guarded against unhandled exceptions (or untrapped errors), you can do one of the following:

In either case, when an error is caught, you can explicitly close all opened channels. (If your CLOSE hook routine does I/O, be careful of the order in which you close your channels.)

The first example below uses TRY‑CATCH to catch unhandled exceptions.

main
...
proc
    try
      begin
        {Main routine code}
      end
    catch (e)          ;Catch anything unexpected
      begin
        close 1 thru 1024
      end
    finally
      begin
        close 1 thru 1024
      end
end

The following example uses $ERR_CATCH to handle untrapped errors.

main
    ...
proc
    onerror ($ERR_CATCH) close_files
    {Main routine code}
close_files,
    close 1 thru 1024
end

Post‑operation hook methods

find_post_operation_hook

public virtual method find_post_operation_hook, void
    mismatch in optional key,           n
    in optional out_rfa,                a
    in optional keynum,                 n
    in flags,                           IOFlags
    inout error,                        int
proc
.
.
.
endmethod

If implemented, called after a FIND operation.

key

(optional) Key value passed to the FIND. (MISMATCH n)

out_rfa

(optional) RFA/GRFA being returned via the GETRFA qualifier. (a)

keynum

(optional) Numeric KEYNUM value. (n)

flags

Set to any IOFlags present. (IOFlags)

error

Set to a runtime error number that occurred during the FIND or else 0. (int)

read_post_operation_hook

public virtual method read_post_operation_hook, void
    inout buffer,                       a
    mismatch in optional key,           n
    in optional out_rfa,                a
    in optional keynum_or_table,        n
    in flags,                           IOFlags
    inout error,                        int
proc
.
.
.
endmethod

If implemented, called after a READ operation (or AlphaEnumerator.Current get property, RowEnumerator.Fill(), or RowEnumerator.indexer[]), or during an iteration of a FOREACH on a Select object).

Important

If the reads_post_operation_hook method is implemented and part of the I/O hooks creation mask, it will override read_post_operation_hook. To enable read_post_operation_hook, you must disable or remove reads_post_operation_hook.

buffer

Record that was read. (a)

key

(optional) Key value passed to the READ. (MISMATCH n)

out_rfa

(optional) RFA/GRFA being returned via the GETRFA: qualifier. (a)

keynum_or_table

(optional) Numeric KEYNUM value or the table index on a Join. (n)

flags

Set to any IOFlags present. (IOFlags)

error

Set to a runtime error number that occurred during the READ or else 0. (int)

reads_post_operation_hook

public virtual method reads_post_operation_hook, void
    inout buffer,                       a
    in optional out_rfa,                a
    in flags,                           IOFlags
    inout error,                        int
proc
.
.
.
endmethod

If implemented, called after a READS operation. This method has been deprecated when using the Select class, to be replaced by the read_post_operation_hook.

Important

If the reads_post_operation_hook method is implemented and part of the I/O hooks creation mask, it will override read_post_operation_hook. To enable read_post_operation_hook, you must disable or remove reads_post_operation_hook.

buffer

Record that was read. (a)

out_rfa

(optional) RFA/GRFA being returned via the GETRFA: qualifier. (a)

flags

Set to any IOFlags present. (IOFlags)

error

Set to a runtime error number that occurred during the READS or else 0. (int)

write_post_operation_hook

public virtual method write_post_operation_hook, void
    inout buffer,                       a
    in optional recnum,                 n
    in optional out_rfa,                a
    in flags,                           IOFlags
    inout error,                        int
proc
.
.
.
endmethod

If implemented, called after a WRITE operation (or AlphaEnumerator.Current set property or AlphaEnumerator.SparseUpdate when using Select).

buffer

Record that was written. (a)

recnum

(optional) Alphanumeric record number that was written (non‑ISAM) or not ^PASSED (ISAM). (n)

out_rfa

(optional) RFA/GRFA being returned via the GETRFA: qualifier. (a)

flags

Set to any IOFlags present. (IOFlags)

error

Set to a runtime error number that occurred during the WRITE or else 0. (int)

writes_post_operation_hook

public virtual method writes_post_operation_hook, void
    inout buffer,                       a
    in optional stored_rfa,             a
    in flags,                           IOFlags
    inout error,                        int
proc
.
.
.
endmethod

If implemented, called after a WRITES operation.

buffer

Record that was written. (a)

stored_rfa

(optional) To be loaded with an RFA or GRFA if GETRFA: qualifier was specified. (a)

flags

Set to any IOFlags present. (IOFlags)

error

Set to a runtime error number that occurred during the WRITES or else 0. (int)

store_post_operation_hook

public virtual method store_post_operation_hook, void
    inout buffer,                       a
    in optional stored_rfa,             a
    in flags,                           IOFlags
    inout error,                        int
proc
.
.
.
endmethod

If implemented, called after a STORE operation.

buffer

Record that was written. (a)

stored_rfa

(optional) To be loaded with an RFA or GRFA if GETRFA: qualifier was specified. (a)

flags

Set to any IOFlags present. (IOFlags)

error

Set to a runtime error number that occurred during the STORE or else 0. (int)

delete_post_operation_hook

public virtual method delete_post_operation_hook, void
    inout error,                        int
proc
.
.
.
endmethod

If implemented, called after a DELETE operation (or the AlphaEnumerator.DeleteCurrent() or RestrictedAlphaEnumerator.DeleteCurrent() method when using Select).

error

Set to a runtime error number that occurred during the DELETE or else 0. (int)

unlock_post_operation_hook

public virtual method unlock_post_operation_hook, void
    in flags,                           IOFlags
    inout error,                        int
proc
.
.
.
endmethod

If implemented, called after an UNLOCK operation.

flags

Set to any IOFlags present. (IOFlags)

error

Set to a runtime error number that occurred during the UNLOCK or else 0. (int)

Dispose  

protected override method Dispose, void
    in disposing, boolean
proc
.
.
.
endmethod

(Synergy .NET only) If implemented, called before the dispose operation.

disposing

Returns true if Dispose() was called explicitly, or false if Dispose() was called implicitly as the object was being destroyed. (boolean)

Note

The exact time when the finalizer executes is nondeterministic and occurs on a different thread. To know when the finalizer executed, you can implement a Dispose() method, which is called when either the hooked channel is closed or the IOHooks object is overwritten; you can also explicitly call IOHooks.Dispose(). You should implement the Dispose() method on .NET in situations where you would have created an overridden destructor in traditional Synergy (for example, to close a log file channel).

Exception hook method

reconnect_hook

public virtual method reconnect_hook, boolean
    in opflag, IOEventMask
    in error, int
proc
    mreturn false
endmethod

Called during connection recovery after the retry time interval has expired and prior to signaling $ERR_SRVCONRTY. If this method is not implemented, false is returned and the $ERR_SRVCONRTY error is generated. By implementing reconnect_hook() and simply returning true, you can choose a different behavior (for example, popping up a message box to query the user or issuing code to do some exception processing). See the Discussion below for more information.

opflag

Set to the IOEventMask flag, indicating the operation being retried. (IOEventMask)

error

Set to the error $ERR_SRVCONRTY. Also, IOHooks.Syserr will be set to the system error number. (int)

Enumerations

IOEventMask enumeration

Sets the bit masks for the I/O operation hook qualifiers.

Mutually exclusive bit mask values:

Clear

Clears all pre‑ or post‑event handler hooks for the channel.

Auto

Enables only the pre‑ or post‑event handler hooks for the channel that have been implemented in the class.

Combinable bit mask values (using the bitwise OR operator):

Find

FIND operation

Read

READ/GET/AlphaEnumerator.Current/RowEnumerator.Fill()/RowEnumerator.indexer[] operation

Reads

READS/GETS/ operation

Write

WRITE/PUT/AlphaEnumerator.Current/AlphaEnumerator.SparseUpdate operation

Writes

WRITES/PUTS operation

Store

STORE operation

Delete

DELETE/AlphaEnumerator.DeleteCurrent() operation

Unlock

UNLOCK operation

Close

CLOSE operation (premask only)

Reconnect

Network reconnect operation due to an I/O socket failure

IOFlags enumeration

One of the following values indicating an I/O statement qualifier:

DIRECTION_REVERSE

DIRECTION:Q_REVERSE or REVERSE

MATCH_GREATEREQUAL

MATCH:Q_GEQ or default

MATCH_EQUAL

MATCH:Q_EQ

MATCH_GREATER

MATCH:Q_GTR

MATCH_RFA

MATCH:Q_RFA or UNLOCK(RFA:)

MATCH_GEN

MATCH:Q_GEN

MATCH_SEQUENTIAL

MATCH:Q_SEQ

MATCH_MASK

Includes all of the flags combined for this group: MATCH_MASK, MATCH_GREATEREQUAL | MATCH_EQUAL | MATCH_GREATER | MATCH_RFA | MATCH_GEN | MATCH_SEQUENTIAL

POSITION_FIRST

POSITION:Q_FIRST or ^FIRST

POSITION_LAST

POSITION:Q_LAST or ^LAST

POSITION_EOF

POSITION:Q_EOF

POSITION_BOF

POSITION:Q_BOF

POSITION_MASK

Includes all of the flags combined for this group: POSITION_MASK, POSITION_FIRST | POSITION_LAST | POSITION_EOF | POSITION_BOF

LOCK_NO_LOCK

LOCK:Q_NO_LOCK or FIND (default lock behavior)

LOCK_NO_TLOCK

LOCK:Q_NO_TLOCK

LOCK_MANUAL

LOCK:Q_MANUAL_LOCK

LOCK_MASK

Includes all of the flags combined for this group: LOCK_MASK, LOCK_NO_LOCK | LOCK_NO_TLOCK | LOCK_MANUAL

FLAG_FIXED

A read(s) hook or a write(s) hook indicates the I/O was issued by a GET/GETS or PUT/PUTS statement

FLAG_GETRFA

The I/O statement included a GETRFA qualifier whose value is present in the optional out_rfa parameter

FLAG_PURGE

A close hook indicates a PURGE statement was issued

FLAG_SELECT

The I/O hook indicates that it was issued by a Select instead of by a READ, READS, WRITE, etc., statement

FLAG_KEYNUM

A read or find hook indicates the statement included a KEYNUM qualifier whose value is present in the optional keynum parameter

Discussion

Because the runtime calls the hook routines, it controls which optional parameters are passed, based on the information available and the context. For hook methods that include optional parameters at the statement level (such as RFA:), you must use the ^PASSED function to test whether the parameter was passed before referencing it. If you don’t use ^PASSED on an optional argument and that argument isn’t passed, an “Argument missing” error ($ERR_ARGMIS) will occur.

The IOHooks constructors take either one or three parameters and have the following signatures:

IOHooks(channel)
new IOHooks(channel, premask, postmask)

or

new IOHooks(Select.From)
new IOHooks(Select.From, premask, postmask)

Only one IOHooks class object can be registered to each channel.

You will need to add code to create a new instance of your event handler class, passing the channel or the Select.From object on which the desired file is open. All event handler methods implemented in the class will be hooked and used during I/O operations.

Note

It is not necessary to assign the resulting object to a handle unless you intend to use the IOReset() method.

For example,

(void)new myhooks(ch)           ;Hook a channel

or

(void)new myhooks(fobj)         ;Hook a Select channel

or

hnd = new myhooks(ch)           ;Save hnd for use later
Note

When managing file channels using one of the Select class From constructors that specifies the filename, the channel number is not available, so you will need to use one of the IOHooks constructors that takes a Select.From object.

When using the Select class, an iteration on the selection (or AlphaEnumerator.MoveNext() or RowEnumerator.MoveNext()) should be hooked using the READS pre‑ and post‑hooks; a record update using the RowEnumerator.Current property should be hooked using the WRITE pre‑ and post‑hooks; and a record deletion using the AlphaEnumerator.DeleteCurrent() method should be hooked using the DELETE pre‑ and post‑hooks. No other I/O operations are hooked while a Select is occurring on a channel (except STORE, UNLOCK, and CLOSE, which can still be done on a Select channel).

A general IOHooks class can be used to control several different channels where different I/O operations are required. The premask and postmask values are used to specify those operations; each bit in the premask and postmask parameters represents an I/O hook method that has been overridden in a class that extends the IOHooks class. If you don’t want to hook all of the methods implemented in the class, you can pass the mask values for the pre‑ and post‑operation flags to indicate which hook methods in the event handler class you do want to use. For example,

hnd = new myhooks(ch, IOEventMask.Read, IOEventMask.Read)

Bits that are set create pre‑ or post‑event handler hooks for the I/O operations that the bits represent. Bits that are not set clear pre‑ or post‑event handler hooks for the I/O operations that the bits represent.

To change which implemented hook methods are to be used during I/O operations, using an instance of the event handler class, you can explicitly call the IOReset() method with new mask values for pre‑ and post‑operation flags. For example,

hnd.IOReset(IOEventMask.Reads, IOEventMask.Reads|IOEventMask.Store)

To unregister the event handler without closing the file, call IOReset() with the Clear mask values for both pre‑ and post‑operation mask. For example,

hnd.IOReset(IOEventMask.Clear, IOEventMask.Clear)

To reset the mask values for both pre‑ and post‑operations back to all methods implemented in the class, you can explicitly call IOReset() like this:

hnd.IOReset(IOEventMask.Auto, IOEventMask.Auto)

As the application executes, I/O operations on hooked channels execute your event handler methods immediately before the operation (pre‑hook) and/or immediately after the operation (post‑hook). When the registered channel is closed, the event handler object is unregistered automatically.

Note

Parameters that are defined INOUT, such as the read or write buffer, can be modified by the hook methods, resulting in altered data read or written. This feature can be very useful (if you want to encrypt data transparently, for example), but it can also be very dangerous, because it hides what goes into and comes out of a file.

To trap an $ERR_SRVCONRTY error during an I/O operation, you must implement your own hooks class that extends the IOExtensions.IOHooks class and overrides the reconnect_hook() method. Returning true from your reconnect_hook() method tells the I/O operation to reset the retry time interval and try again. This method will continue to be called until either the connection is re‑established or your reconnect_hook() method returns false. For more information, see Using connection recovery (Windows).