Selecting and sorting objects by restore order
After the backup or archive query is performed, the application client must determine which objects, if any, are to be restored or retrieved.
Then you sort the objects in ascending order (low to high). This sorting is very important to the performance of the restore operation. Sorting the objects on the restoreOrderExt fields ensures that the data is read from the server in the most efficient order.
All data on disk is restored first, followed by data on media classes that require volume mounts (such as tape). The restoreOrderExt field also ensures that data on tape is read in order with processing starting at the front of a tape and progressing towards the end.
Properly sorting on the restoreOrderExt field means that duplicate tape mounts and unnecessary tape rewinds do not occur.
A non-zero value in the restoreOrderExt.top field correlates to a unique serial access device on the IBM Spectrum Protect™ server. Since a serial access device can only be used by one session / mount point at a time, the application should ensure that if it uses multiple sessions there are not concurrent restores with the same restoreOrderExt.top value. Otherwise the first session are able to access the objects, but other sessions wait until the first session terminates and the device becomes available.
The following example shows how to sort objects by using Restore Order fields.
typedef struct {
dsStruct64_t objId;
dsUint160_t restoreOrderExt;
} SortOrder; /* struct used for sorting */
===================================================================
/* the code for sorting starts from here */
dsmQueryType queryType;
qryBackupData queryBuffer;
DataBlk qDataBlkArea;
qryRespBackupData qbDataArea;
dsInt16_t rc;
dsBool_t done = bFalse;
int i = 0;
int qry_item;
SortOrder sortorder[100]; /* sorting can be done up to 100 items
only right now. Set appropriate
array size to fit your needs */
/*-----------------------------------------------------------------+
| NOTE: Make sure that proper initializations have been done to
| queryType,
| queryBuffer, qDataBlkAre, and qbDataArea.
|
------------------------------------------------------------------*/
qDataBlkArea.bufferPtf = (char*) &qbDataArea;
rc = dsmBeginQuery(dsmHandle, queryType, (void *) &queryBuffer);
/*----------------------------------------+
| Make sure to check rc from dsmBeginQuery
+-----------------------------------------*/
while (!done)
{
rc = dsmGetNextQObj(dsmHandle, &qDataBlkArea);
if ((rc == DSM_RC_MORE_DATA) ||
(rc == DSM_RC_FINISHED))
&&( qDataBlkArea.numBytes))
{
/******************************************/
/* transferring restoreOrderExt and objId */
/******************************************/
sortorder[i].restoreOrderExt = qbDataArea.restoreOrderExt;
sortorder[i].objId = qbDataArea.objId;
} /* if ((rc == DSM_RC_MORE_DATA) || (rc == DSM_RC_FINISHED)) */
else
{
done = bTrue;
/****************************/
/* take appropriate action. */
/****************************/
}
i++;
qry_item++;
} /* while (!done) */
rc = dsmEndQuery(dsmHandle);
/*check rc */
/*****************************************************/
/* sorting the array using qsort. After the call, */
/* sortorder will be sorted by restoreOrderExt field */
/*****************************************************/
qsort(sortorder, qry_item, sizeof(SortOrder), SortRestoreOrder);
/*-----------------------------------------------------------------+
| NOTE: Make sure to extract sorted object ids and store them in
| any data structure you want.
------------------------------------------------------------------*/
/*----------------------------------------------------------------+
| int SortRestoreOrder(SortOrder *a, SortOrder *b)
|
| This function compares restoreOrder fields from two structures.
| if (a > b)
| return(GREATERTHAN);
|| if (a < b)
| return(LESSTHAN);
|| if (a == b)
| return(EQUAL);
|+----------------------------------------------------------------*/
int SortRestoreOrder(SortOrder *a, SortOrder *b)
{
if (a->restoreOrderExt.top > b->restoreOrderExt.top)
return(GREATERTHAN);
else if (a->restoreOrderExt.top < b->restoreOrderExt.top)
return(LESSTHAN);
else if (a->restoreOrderExt.hi_hi > b->restoreOrderExt.hi_hi)
return(GREATERTHAN);
else if (a->restoreOrderExt.hi_hi < b->restoreOrderExt.hi_hi)
return(LESSTHAN);
else if (a->restoreOrderExt.hi_lo > b->restoreOrderExt.hi_lo)
return(GREATERTHAN);
else if (a->restoreOrderExt.hi_lo < b->restoreOrderExt.hi_lo)
return(LESSTHAN);
else if (a->restoreOrderExt.lo_hi > b->restoreOrderExt.lo_hi)
return(GREATERTHAN);
else if (a->restoreOrderExt.lo_hi < b->restoreOrderExt.lo_hi)
return(LESSTHAN);
else if (a->restoreOrderExt.lo_lo > b->restoreOrderExt.lo_lo)
return(GREATERTHAN);
else if (a->restoreOrderExt.lo_lo < b->restoreOrderExt.lo_lo)
return(LESSTHAN);
else
return(EQUAL);
}