Begins a data set scan for the specified data set and returns information about the first data set found.
#include <smstsapi.h> #include <sms.h> CCODE NWSMTSScanDataSetBegin ( UINT32 connection, NWSM_DATA_SET_NAME_LIST *resourceName, NWSM_SCAN_CONTROL *scanControl, NWSM_SELECTION_LIST *selectionList, UINT32 *sequence, NWSM_SCAN_INFORMATION **scanInformation, NWSM_DATA_SET_NAME_LIST **dataSetNames);
(IN) Specifies the connection information returned by NWSMTSConnectToTargetService or NWSMTSConnectToTargetServicEx.
(IN) Points to the starting point or path of the resource to scan.
(IN) Points to the options of the data sets to scan or ignore (see Scan Control Options).
(IN) Points to the data sets to scan or ignore and contains the name as it appears under every name space supported by resourceName.
(OUT) Points to the scanning sequence value (doesn't need to be initialized since it is set by the TSA).
(OUT) Points to the general attributes and information of the first data set that meets the scanning criteria (optional).
(OUT) Points to the name of the first data set that met the scanning criteria (optional).
See Section 9.3, Target Service Return Values for more information.
The following table lists the return values associated with the function.
To build dataSetNames, the Data Set Name Functions described in Storage Management Services Library can be used. The scan information and data set names are known as the data set information by SIDF.
Before NWSMTSScanDataSetBegin is called, the engine must be connected to a TSA and Target Service.
NWSMTSScanDataSetBegin can be called multiple times to initiate concurrent scans. Each time it is called, a different resource name is passed. If concurrent scans are used, the engine should ensure that the data area covered by a resource does not overlap the area covered by another resource.
NWSMTSScanDataSetBegin begins scanning where resourceName is pointing. The engine should copy the information returned by scanInformation and dataSetNames since the buffer is reused when NWSMTSScanDataSetBegin is called again. To free scanInformation and dataSetNames, call NWSMTSScanDataSetEnd.
resourceName can contain a primary resource, a path to a parent, or a fully qualified path to a child. It can be obtained from previous dataSetNames values, or by calling NWSMTSScanTargetServiceResource or NWSMTSListTSResources.
resourceName should be set to the first primary resource name instead of its parent.
There are two special values for resourceName as follows:
ERROR LOG is an ASCII file, which list the errors that occurred during the back-up/restore session.
SKIPPED DATA SETS is a log that indicates the data sets that met the scanning criteria, but were skipped (see Log Files).
Both files are automatically deleted when NWSMTSReleaseTargetService is called. If resourceName is ERROR LOG or SKIPPED DATA SETS, scanInformation and dataSetNames will not contain any valid information.
scanControl determines not only the kinds attribute information returned, but also how much path information is returned, and under which name spaces to search for data sets.
To scan for all data sets, set selectionList to NULL. Otherwise, set it to a list containing the scanning patterns, paths, or explicit data set names to filter (see Data Set Selection Options).
To build resourceName and selectionList, the Data Set Name Functions listed in Storage Management Services Utility Library can be used.
For any path built for resourceName or selectionList, the engine must ensure that the path is properly formatted for the intended name space.
For engines that use SMS DI or SIDF, scanInformation and dataSetNames can be formatted and placed into SIDF transfer buffers by calling NWSMSetNewRecordHeader and NWSMUpdateRecordHeader.
The following table lists the data sets that the file system TSA excludes from the scan operation even when the data sets are explicitly included
If scanControl is set to NULL, the TSA scans the Target Service as if the structure’s values are 0.
The dataSetNames list can be used in many ways such as displaying or naming the data set in a database.
NWSMTSScanDataSetBegin can also perform the following tasks in addition to scanning for data sets to back up:
Build a list of directories and files to display to the user
Check if a data set exists before overwriting it during a restore session
Scan for data sets to be deleted or renamed by passing sequence to NWSMTSDeleteDataSet and NWSMTSRenameDataSet respectively
NWSMTSBuildResourceList, NWSMTSDeleteDataSet, NWSMTSListTSResources, NWSMTSRenameDataSet, NWSMTSScanDataSetEnd, NWSMTSScanNextDataSet, NWSMTSScanTargetServiceResource
#include <smsutapi.h> #include <smstsapi.h> #include <sms.h> /* include file for scan attributes. */ NWSM_DATA_SET_NAME_LIST *resourceName, *dataSetName = NULL; NWSM_DATA_SET_NAME name; NWSM_SCAN_CONTROL scanControl; NWSM_SCAN_INFORMATION *scanInformation = NULL; NWSM_SELECTION_LIST *selectionList; UINT32 sequence, dataSetHandle, openModes, bytesRead, transferBufferSpaceLeft, bytesWritten, transferBufferOffset, maxTransferBufferSize; NWSM_RECORD_HEADER_INFO recordHeaderInfo = {0}; BUFFERPTR transferBuffer; /* Setup resourceName-see NWSMTSListTSResources and NWSMTSScanTargetServiceResource. */ ... /* Gather the TSA's options and get the user's input*/ ... /* Setup scanControl-see the example code for NWSMTSGetUnsupportedOptions and NWSMTSGetTargetScanTypeString. */ ... /* Setup selectionList-see NWSMTSGetTargetSelectionTypeStr.*/ /* begin the back-up session. */ ccode = NWSMTSScanDataSetBegin(connection, resourceName, &scanControl, selectionList, &sequence, &scanInformation, &dataSetName); if(ccode) { if(ClusterEnabled && IsClusterError(ccode)) // For ccode refer Recovery Error Codes if(!Reconnect) // returns 0 if success after n retries {// Cannot call NWSMTSScanDataSetContinue, as there is nothing to continue from. // as this being the beginning call ccode = NWSMTSScanDataSetBegin(connection, resourceName, &scanControl, selectionList, &sequence, &scanInformation, &dataSetName); } else // Handle reconnection error. } else // Handle error } /************************************************************************** * Constructing the name space type info for the resource being * backed up. Will need this for constructing the cursor that is to * be passed to TSA after a fail over / fail back. This is done only * once for a resource. **************************************************************************/ if(!ccode && (sessionInfo->clusterparams)) // if ScanBegin is Success { NWSMGetDataSetName(dataSetNameList, 0L, &dataSetName); cNameSpaceType=dataSetName.nameSpaceType; NWSMTSGetNameSpaceTypeInfo( sessionInfo->connection, cNameSpaceType, &cReverseOrder, &cFirstSeparater, &cSecondSeperater); } /* Set the open modes from the user's selection. The modes were received when the TSA options where gathered */ openModes = user selected modes; /* Create transfer buffer. For more information about maxTransferBufferSize, see Storage Management Services Device Interface. */ transferBuffer = (BUFFERPTR)calloc(1, maxTransferBufferSize); while(!ccode) // Successful ScanBegin { ccode = NWSMTSOpenDataSetForBackup(connection, sequence, openModes, &dataSetHandle); if(ccode) { if(ClusterEnabled && IsClusterError(ccode)) // ccode can be one of NWSMDR_OPEN_FAILURE {// or NWSMDR_READ_FAILURE or NWSMDR_WRITE_FAILURE or NWSMDR_RECONNECT_FAILURE or NWSMDR_TRANSPORT_FAILURE if(!Reconnect) // returns 0 if success after n retries { if(cParent || cChild) // if there is last successful data set { // construct parent or child full path for the last successfully backed up dataset // if only child, cat parent along with it. NWSMPutOneName( (void **)&lastDataSetNameList,// cursor to be used by ScanContinue cNameSpaceType,// Name Space Type obtained after successful ScanBegin call above 0L,//First param contains DataSetnameList so this is set to zero cReverseOrder, (char *)&cFirstSeparater, (char *)&cSecondSeperater, (char *)&(cFullPath->string)); // The full path of last successfully backed up child or parent ccode=NWSMTSScanDataSetContinue(sessionInfo->connection, resourceName, &sessionInfo->scanControl, sessionInfo->selectionList, lastDataSetNameList, // cursor &sequence, &sessionInfo->scanInfo, &dataSetNameList); } else // if this is the first data set, then there is nothing to continue from { // so call ScanBegin to start from first ccode = NWSMTSScanDataSetBegin(connection, resourceName, &scanControl, selectionList, &sequence, &scanInformation, &dataSetName); } } else // Handle reconnection error. } else // Handle error } /* Display the data set name to the user. See Storage Management Services Utility Library for the function below. */ NWSMGetOneName(dataSetName, &name); if (scanInformation->parentFlag) { /* Display name.name as a parent (e.g., directory). */ ... } else { /* Display name.name as a child (e.g., a file). */ ... } /* Usually the transfer buffer size is negotiated between SMS DI and the engine-see NWSMSDSessionOpenForWriting in the SMS DI documentation. However, it is set to an assumed size to keep this example relatively simple. For information on transferBufferDataOffset see the Storage Device API document's NWSMSDSessionOpenForWriting. */ transferBufferSpaceLeft = maxTransferBufferSize - transferBufferDataOffset; /* Put the data set information and data set data into an SIDF data set, and then into the transfer buffer. Here, we assume that the transfer buffer is defined somewhere else (see the Storage Device API document's NWSMSDSessionOpenForWriting). For information on NWSMDOSTimeToECMA see Storage Management Services Utility Library. */ recordHeaderInfo.isSubRecord = FALSE; recordHeaderInfo.dataSetName = dataSetName; recordHeaderInfo.scanInformation = scanInformation; NWSMDOSTimeToECMA(NWSMGetCurrentTime(), &recordHeaderInfo.archiveDateAndTime); NWSMSetNewRecordHeader(&transferBuffer, &transferBufferSpaceLeft, &bytesWritten, CRC_YES, &recordHeaderInfo); /* Here we assume that the transfer buffer always has enough room to receive the data set data, that NWSMTSReadDataSet retrieves all of the data set data on the first call, and that the transfer buffer is completely filled. */ ccode = NWSMTSReadDataSet(connection, dataSetHandle, transferBufferSpaceLeft, &bytesRead, &transferBuffer[transferBufferDataOffset]); if(ClusterEnabled) { if(!ccode) { if(scanInformation->parentFlag) // Store parent as it is successfully backedup else // Store child as it is successfully backedup } if(IsClusterError(ccode)) // ccode can be one of NWSMDR_OPEN_FAILURE {// or NWSMDR_READ_FAILURE or NWSMDR_WRITE_FAILURE or NWSMDR_RECONNECT_FAILURE or NWSMDR_TRANSPORT_FAILURE if(!Reconnect) // returns 0 if success after n retries { if(cParent || cChild) // if there is last successful data set { // construct parent or child full path for the last successfully backed up dataset NWSMPutOneName( (void **)&lastDataSetNameList,// cursor to be used by ScanContinue cNameSpaceType,// Name Space Type obtained after successful ScanBegin call above 0L,//First param contains DataSetnameList so this is set to zero cReverseOrder, char *)&cFirstSeparater, (char *)&cSecondSeperater, (char *)&(cFullPath->string)); // The full path of last successfully backed up child or parent ccode=NWSMTSScanDataSetContinue(sessionInfo->connection, resourceName, &sessionInfo->scanControl, sessionInfo->selectionList, lastDataSetNameList, // cursor &sequence, &sessionInfo->scanInfo, &dataSetNameList); } else // if this is the first data set, then there is nothing to continue from { // so call ScanBegin to start from first ccode = NWSMTSScanDataSetBegin(connection, resourceName, &scanControl, selectionList, &sequence, &scanInformation, &dataSetName); } } else // Handle reconnection error. } else // Handle error } /* Keep track of how many bytes are written to the transfer buffer. This information is needed for recordHeaderInfo */ bytesWritten =+ bytesRead; recordHeaderInfo.recordSize += bytesRead; /* Since the transfer buffer is full, update the data set header size and CRC information, then send the transfer buffer to SMS DI. SMS DI will write the transfer buffer to the media. See NWSMSDSessionWriteData in Storage Device API for more information. */ NWSMUpdateRecordHeader(&recordHeaderInfo); ... /* close the data set and get the next one */ NWSMTSCloseDataSet(connection, &dataSetHandle); ccode = NWSMTSScanNextDataSet(connection, &sequence, &scanInformation, &dataSetName); if(ccode) { if(ClusterEnabled && IsClusterError(ccode)) // ccode can be one of NWSMDR_OPEN_FAILURE {// or NWSMDR_READ_FAILURE or NWSMDR_WRITE_FAILURE or NWSMDR_RECONNECT_FAILURE or NWSMDR_TRANSPORT_FAILURE if(!Reconnect) // returns 0 if success after n retries { if(cParent || cChild) // if there is last successful data set { // construct parent or child full path for the last successfully backed up dataset // if only child, cat parent along with it. NWSMPutOneName( (void **)&lastDataSetNameList,// cursor to be used by ScanContinue cNameSpaceType,// Name Space Type obtained after successful ScanBegin call above 0L,//First param contains DataSetnameList so this is set to zero cReverseOrder, (char *)&cFirstSeparater, (char *)&cSecondSeperater, (char *)&(cFullPath->string)); // The full path of last successfully backed up child or parent ccode=NWSMTSScanDataSetContinue(sessionInfo->connection, resourceName, &sessionInfo->scanControl, sessionInfo->selectionList, lastDataSetNameList, // cursor &sequence, &sessionInfo->scanInfo, &dataSetNameList); } else // if this is the first data set, then there is nothing to continue from { // so call ScanBegin to start from first ccode = NWSMTSScanDataSetBegin(connection, resourceName, &scanControl, selectionList, &sequence, &scanInformation, &dataSetName); } } else // Handle reconnection error. } else // Handle error } } /* end while loop */ /* If the scanning functions did not return an error, end the scan */ NWSMTSScanDataSetEnd(connection, &sequence, &scanInformation, &dataSetName);