Tivoli Header

Tivoli Storage Manager Using the Application Program Interface

Receive Data With a Restore or Retrieve Procedure

After a query is made and a session is established with the TSM server, the procedure to restore or retrieve data is to:

  1. Query the TSM server for either backup or archive data.
  2. Determine the objects to restore or retrieve from the server.
  3. Sort the objects on the Restore Order field.
  4. Send the dsmBeginGetData call with the list of objects that you want to access.
  5. Send the dsmGetObj call to obtain each object from the system. Multiple dsmGetData calls might be needed for each object to obtain all associated object data. Send the dsmEndGetObj call after all data for an object is obtained.
  6. Send the dsmEndGetData call after all data for all objects is received, or to end the receive operation.

Query the Server

Before you can begin any restore or retrieve operation, first query the TSM server to determine what objects you can receive from storage. To send the query, the application must enter the proper parameter lists and structures for the dsmBeginQuery call. This includes the file space that the query will examine and pattern-match entries for the high-level and low-level name fields. If the session was initialized with a NULL owner name, it is not necessary to specify the owner field. However, if the session was initialized with an explicit owner name, only objects that explicitly have that owner name associated with them are returned.

The Point-in-time BackupQuery supplies a snapshot of the system at a given time. By specifying a valid date, you can query all files that were backed up to that time. Even if an object has an active backup from a later date, point-in-time overrides an object state so that the previous inactive copy is returned. An example of this is in pitDate. You must be connected to a Version 3 server to use point-in-time BackupQuery.

A query returns all information that was originally stored with the object, in addition to the following:

copyId
The copyIdHi and copyIdLo values provide an eight-byte number that uniquely identifies this object for this node in TSM storage. Use this ID to request a specific object from storage for restore or retrieve processing.

restoreOrderExt
The restoreOrderExt value provides a mechanism for receiving objects from TSM storage in the most efficient manner possible. Sort the objects to restore on this value to ensure that tapes are mounted only once and are read from front to back.

You must keep some or all of the query information for later processing. Keep the copyId and restoreOrderExt fields because they are needed for the actual restore operation. You must also keep any other information needed to properly open a data file or identify a destination.

Call dsmEndQuery to finish the query operation.

Select Objects to Receive

Once the backup or archive query is performed, the application client must determine which objects, if any, are to be restored or retrieved.

Sort Objects by Restore Order

Once the objects to restore or retrieve are selected, sort them 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.

Following is an example of sorting objects by using Restore Order fields.

Figure 16. An Example of Sorting Objects With the 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);                                                           |
|}                                                                               |
+--------------------------------------------------------------------------------+

Start the dsmBeginGetData Call

Once you select and sort the objects to receive, submit them to TSM for either a restore or retrieve. The dsmBeginGetData call begins a restore or retrieve operation. Complete the information for these two parameters in these calls:

mountWait
This parameter tells the server whether the application client is willing to wait for offline media to be mounted in order to obtain data for an object, or whether that object should be skipped during processing of the restore or retrieve operation.

dsmGetObjListP
This parameter is a data structure that contains a list of all objIds that will be restored or retrieved. Each objId is associated with a partialObjData structure that describes whether the entire objId or only a particular section of the object will be retrieved.

Each objId is eight bytes in length, so a single restore or retrieve request can contain thousands of objects. The number of objects to request in a single call is limited to DSM_MAX_GET_OBJ or DSM_MAX_PARTIAL_GET_OBJ.

The objects are returned to the application client in the order you requested.

Receive Each Object to Restore or Retrieve

Once the dsmBeginGetData call is sent, perform the following procedure to receive each object that is sent from the server:

  1. Send the dsmGetObj call to identify the object that you requested from the data stream and, to obtain the first block of data that is associated with the object.
  2. Send more dsmGetData calls, as necessary, to obtain the remaining object data.

The DSM_RC_MORE_DATA return code means that a buffer was returned and you should call dsmGetData again. The DSM_RC_FINISHED return code means that the last buffer was returned and you should call dsmEndGetObj again. Check the DataBlk.num Bytes for the actual number of returned bytes.

When you obtain all data for an object, you must send a dsmEndGetObj call. If more objects will be received, send the dsmGetObj call again. If you need to stop the process (normally or abnormally), send the dsmEndGetData call.

Start the dsmEndGetData Call

After all data for all requested objects is received, send the dsmEndGetData call. You can also use this call to discard any remaining data in the restore stream for all objects not yet received. This will flush the data from the server to the client. However, using this method might take time to complete. If you need to end a restore, use dsmTerminate to close the session.


[ Top of Page | Previous Page | Next Page | Table of Contents | Index ]