Redirected IO
This chapter describes the use of Redirected IO in the Viewer. Many developers using the earlier versions of this technology expressed a need to read file data from non-file system based sources. For instance, the developer might want to read the file from a database on a server. Perhaps the developer is downloading the file over a slow link, and wants to see the first screen of a document before the download is completed, or only wants to download enough to view the first screen. To address these requests, developers now have total control over access to a file via Oracle Outside In’s redirected IO mechanism.
This chapter includes the following sections:
Using Redirected IO
A developer can redirect the IO for an input or output file by providing a data structure that contains pointers to custom IO routines for reading and writing. This data structure is passed in place of a typical file specification. The developer must set the dwSpecType parameter of the SCCVWVIEWFILE40 or SCCVWVIEWFILE80 structure to IOTYPE_REDIRECT when the SCCVW_VIEWFILE message is sent.
When dwSpecType is set this way, the pSpec element must contain a pointer to a developer-defined data structure that begins with a BASEIO structure (defined in baseio.h). The BASEIO structure contains pointers to the basic IO functions for the view window’s IO system such as Read, Seek, Tell, etc. The developer must initialize these function pointers to their own functions that perform IO tasks. Beyond the BASEIO element, the developer may place any other data. For instance, a developer’s structure might look like the following:
typedef struct MYFILEtag
{
BASEIO sBaseIO; /* must be the first element */
VTDWORD dwMyInfo1;
VTDWORD dwMyInfo2;
.
.
.
} MYFILE;
Since the pSpec passed is essentially the file handle that the view window uses, the developer can redirect the IO on a file-by-file basis while still viewing regular disk-based files.
The BASEIO structure is defined as follows:
typedef struct BASEIOtag
{
IOCLOSEPROC pClose;
IOREADPROC pRead;
IOWRITEPROC pWrite;
IOSEEKPROC pSeek;
IOTELLPROC pTell;
IOGETINFOPROC pGetInfo;
IOOPENPROC pOpen; /* pOpen *MUST* be set to NULL. */
#ifndef NLM
IOSEEK64PROC pSeek64;
IOTELL64PROC pTell64;
#endif
VTVOID *aDummy[3];
} BASEIO, * PBASEIO;
The developer must implement the Close, Read, Seek, Tell and GetInfo routines. The Write routine can be a dummy routine and the Open routine must be set to NULL. The first parameter to each of these routines is called hFile and is of the type HIOFILE. HIOFILE is simply the VTLPVOID to your data structure that was passed in the pSpec parameter of the SCCVWVIEWFILE40 or SCCVWVIEWFILE80 structure.
The sample source code for a simple implementation of Redirected IO is in the directory SAMPLES/REDIRect. This sample redirects the technology’s IO through the fopen, fgetc, fseek, ftell and fclose run-time library routines.
Note: Redirected IO does not cache the whole file! Seeks can and will occur throughout the file during the course of viewing. If the developer is implementing redirected IO on a slow or sequential link, it is the developer’s responsibility to cache the file locally.
IOClose
Closes the file identified by hFile and cleans up all memory associated with the file.
Prototype
IOERR IOClose(
HIOFILE hFile);
Parameters
- hFile: Identifies the file to be closed. Should be cast into a pointer to your data structure (MYFILE in the preceding discussion).
Return Values
-
IOERR_OK: Close was successful.
-
IOERR_UNKNOWN: Some error occurred on close.
IORead
Reads data from the current file position forward and resets the position to the byte after the last byte read.
Prototype
IOERR IORead(
HIOFILE hFile,
VTBYTE * pData,
VTDWORD dwSize,
VTDWORD * pCount);
Parameters
-
hFile: Identifies the file to be read. Should be cast into a pointer to your data structure (MYFILE in the preceding discussion).
-
pData: Points to the buffer into which the bytes should be read. Will be at least dwSize bytes big.
-
dwSize: Number of bytes to read.
-
pCount: Points to the number of bytes actually read by the function. This value is only valid if the return value is IOERR_OK.
Return Values
-
IOERR_OK: Read was successful. pCount contains the number of bytes read and pData contains the bytes themselves.
-
IOERR_EOF: Read failed because the file pointer was beyond the end of the file at the time of the read.
-
IOERR_UNKNOWN; Read failed for some other reason.
IOWrite
Writes data from the current file position forward and resets the position to the byte after the last byte written.
Note: This function has been fully documented only for completeness. OEMs who use redirected IO do not need to implement writing and the IOWrite function should do nothing but return IOERR_UNKNOWN.
Prototype
IOERR IOWrite(
HIOFILE hFile,
VTBYTE * pData,
VTDWORD dwSize,
VTDWORD * pCount);
Parameters
-
hFile: Identifies the file where the data is to be written. Should be cast into a pointer to your data structure (MYFILE in the preceding discussion).
-
pData: Points to the buffer from which the bytes should be written. It must be at least dwSize bytes big.
-
dwSize: Number of bytes to write.
-
pCount: Points to the number of bytes actually written by the function. This value is only valid if the return value is IOERR_OK.
Return Values
-
IOERR_OK: Write was successful, pCount contains the number of bytes written.
-
IOERR_UNKNOWN: Write failed for some reason.
IOSeek
Moves the current file position.
Prototype
IOERR IOSeek(
HIOFILE hFile,
VTWORD wFrom,
VTLONG lOffset);
Parameters
-
hFile: Identifies the file to be read. Should be cast into a pointer to your data structure (MYFILE in the preceding discussion).
-
wFrom: One of the following values:
-
IOSEEK_TOP: Move the file position lOffset bytes from the top (beginning) of the file.
-
IOSEEK_BOTTOM: Move the file position lOffset bytes from the bottom (end) of the file.
-
IOSEEK_CURRENT: Move the file position lOffset bytes from the current file position.
-
-
lOffset: Number of bytes to move the file pointer. A positive value moves the file pointer forward in the file and a negative value moves it backward. If a requested seek value would move the file pointer before the beginning of the file, the file pointer should remain unchanged and IOERR_UNKNOWN should be returned. Seeking past EOF is allowed. In that case IOERR_OK should be returned. IOTell would return the requested seek position and IORead should return IOERR_EOF and 0 bytes read.
Return Values
-
IOERR_OK: Seek was successful.
-
IOERR_UNKNOWN: Seek failed for some reason.
IOTell
Returns the current file position.
Prototype
IOERR IOTell(
HIOFILE hFile,
VTDWORD * pOffset);
Parameters
- hFile: Identifies the file to be closed. Should be cast into a pointer to your data structure (MYFILE in the preceding discussion).0
Return Values
- hFile: Identifies the file to be closed. Should be cast into a pointer to your data structure (MYFILE in the preceding discussion).1
IOGetInfo
Returns information about an open file.
Prototype
IOERR IOGetInfo(
HIOFILE hFile,
VTDWORD dwInfoId,
VTVOID * pInfo);
Parameters
- hFile: Identifies the file to be closed. Should be cast into a pointer to your data structure (MYFILE in the preceding discussion).2
Return Values
- hFile: Identifies the file to be closed. Should be cast into a pointer to your data structure (MYFILE in the preceding discussion).4
IOGENSECONDARY and IOGENSECONDARYW Structures
These structures are passed to the developer through the IOGetInfo function. They allow the developer to tell the technology where a secondary file, needed to view the primary file, is located.
The SpecType of the original file determines which of these two structures is used. If the SpecType is IOTYPE_UNICODEPATH, IOGENSECONDARYW is used. pFileName will point to a Unicode string terminated with a NULL WORD. For all other SpecTypes, IOGENSECONDARY is used and pFileName will point to a string terminated with a NULL BYTE.
The following is a C data structure defined in SCCIO.H:
typedef struct
{
VTDWORD dwSize;
VTLPBYTE pFileName;
VTDWORD dwSpecType;
VTLPVOID pSpec;
VTDWORD dwOpenFlags
} IOGENSECONDARY, * PIOGENSECONDARY;
typedef struct
{
VTDWORD dwSize;
VTLPWORD pFileName;
VTDWORD dwSpecType;
VTLPVOID pSpec;
VTDWORD dwOpenFlags
} IOGENSECONDARYW, * PIOGENSECONDARYW;
- hFile: Identifies the file to be closed. Should be cast into a pointer to your data structure (MYFILE in the preceding discussion).5
File Types That Cause IOGETINFO_GENSECONDARY
This section provides information about applicable file types.
- hFile: Identifies the file to be closed. Should be cast into a pointer to your data structure (MYFILE in the preceding discussion).7
IOSEEK64PROC / IOTELL64PROC
These functions are for seek/tell using 64-bit offsets. These functions are not used by default. Rather, they are used if the IOGETINFO_64BITIO message returns IOERR_TRUE. This is so redirected I/O using strictly 32-bit I/O is unaffected.
IOSeek64
Moves the current file position.
Prototype
IOERR IOSeek64(
HIOFILE hFile,
VTWORD wFrom,
VTOFF_T offset);
Parameters
The parameter information is the same as for IOSeek(). However, the size of the VTOFF_T offset for IOSeek64() is 64-bit unlike the 32-bit offset in IOSeek().
IOTell64
Returns the current file position.
Prototype
IOERR IOTell64(
HIOFILE hFile,
VTOFF_T * pOffset);
Parameters
The parameter information is the same as for IOTell(). The only change is the use of a pointer to a 64-bit parameter for returning the offset.