The db2GetSnapshot() routine returns snapshot data as a self-describing data stream in the user supplied buffer. Data is returned in the logical data groupings described in Snapshot Requests.
Each item returned by a snapshot request contains fields that specify its size and type (see Snapshot Output). The size can be used to parse through the returned data.
Size can also be used to skip over a logical data group. For example, to skip over a db2 record you need to determine
size of the db2 logical data grouping + sizeof(sqlm_header_info)
bytes in the data stream.
The following code sample illustrates how an application could parse through the data returned in the snapshot output buffer. The element datastream passed into the function is the buffer returned from the db2GetSnapshot() call.
#include "stdlib.h" #include "stdio.h" #include "sqlutil.h" #include "string.h" #include "sqlmon.h" // System Monitor interface void pocess_buffer(sqlm_header_info *datastream) { long data_len = datastream->size; sqlm_header_info *traversal_ptr = datastream; // presume that we aren't interested in the "collected" data // elements ++traversal_ptr; //------------------------------------------------------------------------ // PROCESS EACH RECORD THAT MAY BE RETURNED IN THE SNAPSHOT OUTPUT BUFFER //------------------------------------------------------------------------ while (data_len > 0) { // Switch on the element switch (traversal_ptr->element) { case SQLM_ELM_DB2: // Process the database manager snapshot printf("Processing database manager snapshot\n"); // ... break; case SQLM_ELM_DBASE: // Process the snapshot ... printf("Processing database snapshot\n"); // ... break; case SQLM_ELM_APPL: printf("Processing application snapshot\n"); // ... break; case SQLM_ELM_APPL_INFO: printf("Processing list application\n"); // ... break; case SQLM_DCS_APPL_INFO: printf("Processing list dcs application\n"); // ... break; case SQLM_ELM_TABLE_LIST: printf("Processing list tables\n"); // ... break; case SQLM_ELM_DBASE_LOCK_LIST: printf("Processing snapshot for locks on database\n"); // ... break; case SQLM_ELM_APPL_LOCK: { printf("Processing snapshot for locks for application\n"); // ... break; case SQLM_ELM_TABLESPACE_LIST: { printf("Processing snapshot for tablespaces\n"); // ... break; default: // Do nothing. This could be a new logical data element we aren't // interested in, or it could be one of the collected data elements. } // end check the current snapshot buffer structure // Skip the record we just processed data_len -= traversal_ptr->size + sizeof(sqlm_header_info); traversal_ptr = (sqlm_header_info *)((char *)traversal_ptr + traversal_ptr->size + sizeof(sqlm_header_info)); } // end while there are top-level structures in the snapshot output buffer }
Processing portions of the new data stream is similar to processing the uppermost portion of the stream. The following is an example of how a user could pick out the db name from a database logical grouping of data elements, to return it in a pre-allocated string.
A similar approach can be taken for processing any data element from the stream.
void process_db2_info(sqlm_header_info *db2inf, char *db_name) { long data_size = db2inf->header.size; sqlm_header_data *traverse_ptr = (sqlm_header_data *)db2inf; traverse_ptr++; while(data_size) { switch(traverse_ptr->header.element) { case SQLM_ELM_DB_NAME: memcpy(db_name, traverse_ptr->data, traverse_ptr->header.size); // Add the null terminator db_name[traverse_ptr->header.size] = '\0'; break; // cases to access other elements of interest // ... default: break; } data_size -= (traverse_ptr->header.size + sizeof(sqlm_header_info)); traverse_ptr = (sqlm_header_data *)((char *)traverse_ptr->header.size + sizeof(sqlm_header_info)); } }