Reads data sets on the Target Service, formats the data according to SIDF, and returns it in a buffer.
#include <smstsapi.h> CCODE NWSMTSReadDataSets ( UINT32 connection, UINT32 scanSequence, UINT32 openMode, UINT32 bytesToRead, BUFFERPTR buffer, UINT32 *bytesRead, UINT32 *done, UINT32 *readHandle);
(IN) Specifies the connection information returned by NWSMTSConnectToTargetService or NWSMTSConnectToTargetServiceEx.
(IN) Specifies the scanning sequence value returned by NWSMTSScanDataSetBegin.
(IN) Specifies the generic and TSA-specific open mode to apply to all the data sets that can fit the buffer (see Open Modes for possible values).
(IN) Specifies the amount of free space in the buffer.
(OUT) Points to the buffer to contain the data (must be at least bytesToRead bytes).
(OUT) Points to the number of bytes read into buffer.
(OUT) Points to a boolean value indicating if NWSMTSReadDataSets should be called again:
(IN/OUT) Points to the iteration handle (should be zero the first time NWSMTSReadDataSets is called).
See Section 9.3, Target Service Return Values for more information.
The following table lists the return values associated with the function.
ReadDataSets is an enhanced version of ReadDataSet which helps in backing up small files faster. It is used during backup to collect all requested information about possibly more than one data set. Eventually, the OUT buffer will contain the data in System Independent Data Format (SIDF).
In the cases when the data set data is larger than the size of the buffer, it behaves similar to the ReadDataSet wherein it has to be called repeatedly as it returns portions of the data set at a time.
For instances when the data for more than one data set is able to fit within the buffer, it shall be appended one after another. It formats the File Headers (or Record Headers) and File Continuation Headers (or Sub-Record Headers) in the buffer. This facilitates reading more than one data set on a single call to ReadDataSets.
This call takes care of open/reading/closing of data sets (OpenDataSetForBackup, ReadDataSet and CloseDataSet as well as calling ScanNextDataSet).
The data returned in the buffer does not include unused bytes at the end. The unused value will be bytesToRead - *bytesRead. The unused part of the buffer will not become zero by this call. NWSMPadBlankSpace can be used to fill the unused space in buffer with zeroes.
Before NWSMTSReadDataSets is called, NWSMTSScanDataSetBegin must be called to initiate the scan.
done will be freed on the last successful read.
NWSMTSReadDataSets reads the data for a set of data sets into buffer (if SIDF is used). If the buffer cannot contain all of the data set’s data, NWSMTSReadDataSets must be called repeatedly to retrieve all data.
If buffer can accommodate data for more than one data set, all data for those data sets will be returned. done indicates if data for all data sets have been read. Normally when done is FALSE, bytesRead will be equal to bytesToRead except when some intermediate data sets were not read.
IMPORTANT:This API is not supported in NetWare 6.5.
NWSMTSCloseDataSet, NWSMTSOpenDataSetForBackup, NWSMTSReadDataSet, NWSMTSScanDataSetBegin, NWSMTSScanDataSetEnd, NWSMTSScanNextDataSet
#include <smsutapi.h> #include <smstsapi.h> NWSM_DATA_SET_NAME_LIST *resourceName; NWSM_DATA_SET_NAME name; NWSM_SCAN_CONTROL scanControl; NWSM_SCAN_INFORMATION *scanInformation=NULL; NWSM_SELECTION_LIST *selectionList; UINT32 sequence, openModes, bytesRead, transferBufferSpaceLeft, bytesWritten, transferBufferOffset, maxTransferBufferSize; NWSM_RECORD_HEADER_INFO recordHeaderInfo = {0}; BUFFERPTR transferBuffer; /* Setup resource name - see NWSMListTSResources and NWSMTSScanTargetServiceResource. */ /* Gather the TSA options and get the user’s input*/ /* Setup scanControl */ /* Setup selectionList - see NWSMTSGetTargetSelectionTypeStr */ /* Begin the backup session. */ NWSMTSScanDataSetBegin(connection, resourceName, &scanControl, selectionList, &sequence, &scanInformation, &dataSetName); /*Set the open modes from the user’s selection. The modes were received when the TSA options were gathered. */ openModes = user selected modes; /* Create Transfer Buffer. The larger the TB, the faster it backs up */ transferBuffer = (BUFFERPTR) calloc(1, maxTransferBufferSize); /* Initialize the current transferBuffer space to maximum.*/ currentTBSpace = initialTBSpace = session.transferBufferInfo.maxTransferBufferSize - session.transferBufferInfo.transferBufferDataOffset; /* It will be nice to start using NWSMTSReadDataSets now. */ do { /* Check for user intervention. Hopefully he won’t. */ if ((ccode = CheckForOperatorAbort()) != 0) goto Return; /* Read as many data sets as possible in one shot. Depends on buffer size though. */ NWSMTSReadDataSets (connection, sequence, openModes, currentTBSpace, transferBufferPtr, &bytesRead, &done, &readHandle) ; /* Display number of bytes written to TB. */ StatusTotalWritten(bytesRead); myHeaderSize = transferBufferData ; /* Update the TB data */ transferBufferData += bytesRead ; myBufferSize = transferBufferData - myHeaderSize ; myBufferPtr = transferBufferPtr ; /* We are not sure which data sets got backed up with the call to NWSMTSReadDataSets. So get and display all data set info for all data sets contained in TB. User will again be happy to know. */ while (myBufferSize) { /* While there is data in the TB, get the record/subrecord header from TB */ ccode = NWSMGetRecordHeaderOnly (&myBufferPtr, &myBufferSize, &recordHeaderInfo) ; if (!ccode) { /* If we have a record/subrecord, get the data from the transfer buffer. */ if ((recordHeaderInfo.dataSetInfoRetrieved == DATA_SET_INFO_NOT_STARTED)|| (recordHeaderInfo.dataSetInfoRetrieved == DATA_SET_INFO_SPANNED)) NWSMGetDataSetInfo (&myBufferPtr, &myBufferSize, &recordHeaderInfo) ; /* If all data retrieved from current transfer buffer, break and get the next transfer buffer. */ if (!myBufferSize) break; if (recordHeaderInfo.dataSetInfoRetrieved == DATA_SET_INFO_COMPLETE) { /* Data in the recordHeaderInfo.dataSetName and recordHeaderInfo.scanInformation can now be used. */ if ((_ccode = NWSMGetOneName ((recordHeaderInfo.dataSetName, &name)) != 0) { if (NWSMConvertError (connection, _ccode, errorMessage)) sprintf (errorMessage, GetMessage (EM_UNDEFINED_ERROR), _ccode); StatusDisplayError (TRUE, GET_ONE_NAME_ERR, _ccode); } else { /* Display the data set name to the user. */ if (recordHeaderInfo.scanInformation->parentFlag) { /* Display name.name as a parent (e.g., directory) */ StatusDirectoryName (name.nameSpaceType, name.name); recordHeaderInfo.pathIsFullyQualified = TRUE; } else { /* Display name.name as a child (e.g., file) */ StatusFileName (name.name); if (withParentHandle) recordHeaderInfo.pathIsFullyQualified = FALSE; else recordHeaderInfo.pathIsFullyQualified = TRUE; } } } /* Check again if all data retrieved from current transfer buffer, break and get the next transfer buffer. */ if (!myBufferSize) break; /* Update TB information. */ myBufferPtr += recordHeaderInfo.recordSize ; myBufferSize -= recordHeaderInfo.recordSize ; } else break; } transferBufferPtr += bytesRead ; if (done) { NWSMPadBlankSpace ( transferBufferPtr, currentTBSpace-bytesRead)); ccode = WriteTransferBufferToMedia ( &bufferIndex, isFirstBuffer, &transferBufferData, FALSE, &transferBufferPtr); } else { ccode = WriteTransferBufferToMedia ( &bufferIndex, isFirstBuffer, &transferBufferData, TRUE, &transferBufferPtr); } if (ccode != 0) { #if defined (DEBUG_CODE) DEBUG_BEGIN printf ("BkTgt: WTBToMedia = 0x%X (%s:%u)\n", ccode, __FILE__, __LINE__); DEBUG_END #endif goto Return; } break; } if (isFirstBuffer) isFirstBuffer = FALSE; currentTBSpace = initialTBSpace; } }while (!done) ; /* We’ve reached the end and that was real fast. It will be nice to clean up. */ /* Cleaning up is normally a pain but its so easy here*/
Returns NWSMTSEndReadDataSets (connection, &readHandle);