/******************************************************************************* ** ** Source File Name = dbsnap.c 1.7 ** ** Licensed Materials - Property of IBM ** ** (C) COPYRIGHT International Business Machines Corp. 1995, 1999 ** All Rights Reserved. ** ** US Government Users Restricted Rights - Use, duplication or ** disclosure restricted by GSA ADP Schedule Contract with IBM Corp. ** ** ** PURPOSE : to demonstrate the use of DATABASE MONITOR SNAPSHOT APIs ** ** The following illustrates how to issue a snapshot and process the output. ** It prints database lock snapshots. Printing routines for other ** request types are left to the reader to complete as an exercise... ** ** OTHER APIs USED : ** INSTANCE ATTACH sqleatin() ** ** EXTERNAL FUNCTIONS USED IN CODE SAMPLE: ** check_error : Checks for SQLCODE error, and prints out any ** [in util.c] related information available. ** ** ** EXTERNAL DEPENDENCIES : ** - Ensure existence of database for precompile purposes. ** - Compile and link with the IBM Cset++ compiler (AIX and OS/2) ** or the Microsoft Visual C++ compiler (Windows) ** or the compiler supported on your platform. ** ** For more information about these samples see the README file. ** ** For more information on programming in C, see the: ** - "Programming in C and C++" section of the Application Development Guide ** For more information on Building C Applications, see the: ** - "Building C Applications" section of the Application Building Guide. ** ** For more information on the SQL language see the SQL Reference. ** *******************************************************************************/ /****************************************************************************** The Database Monitor Snapshot API #include "sqlca.h" #include "sqlutil.h" Defines the data elements returned by sqlmonss #include "sqlmon.h" #include "util.h" int SQL_API_FN sqlmonss(unsigned long version, char *reserved, sqlma *sqlma_ptr, unsigned long buffer_length, void *buffer_ptr, sqlm_collected *collected, struct sqlca *sqlca ); The 'sqlma' structure specifies the data to snapshot, which is returned in a *user allocated* buffer, as a series of contiguous data blocks. A utility function, 'Estimate buffer size (sqlmonsz)' may be called to estimate how big this buffer should be. REF REFID=XXXXX. Data is returned on a snapshot, only if the Database Manager is collecting it. A set of Database Monitor Switches instruct the Database Manager to collect Monitoring data. REF REFIX=XXXXX2. note: It is not necessary to have a database connection to issue a snapshot request. INPUT: version: SQLM_DBMON_VERSION1 - only return data that would be available on a DB2 version 1 system SQLM_DBMON_VERSION2 - return Version 2 data sqlma: This structure contains an array of sqlm_obj_struct, where each one is a request for Monitored data. obj_num: Number of Database monitor requests. obj_var: Array of requests (sqlm_obj_struct). sqlm_obj_struct: Specifies a request for information about certain DB2 activities at a particular level, and/or for a specific object. If the request is for a specific object, then this object identifier must be provided in the object or agent_id field, depending on the request type. obj_type: To obtain system-wide information: CLP equivalent: SQLMA_DB2 Information and cumulative counters at get snapshot for dbm the database manager level. SQLMA_APPLINFO_ALL Application identification information list applications all applications currently connected to a database that is managed by the DB2 instance. SQLMA_DCS_APPLINFO_ALL Application identification information list dcs applications for all DCS application currently connected to a database that is managed by the DB2 instance. SQLMA_APPL_ALL Application level information and get snapshot for all apps. counters. Returns the same information as SQLMA_APPL or SQLMA_AGENT_ID. SQLMA_DBASE_ALL Database level information and i get snapshot for all databases counters. Returns the same information as SQLMA_DBASE. To obtain information about a particular database: SQLMA_DBASE Database level information and counters get snapshot for database for a database. Information is returned on 'dbname' only if there is at least one application connected to the database. note: When a Database monitor switch is off, switch controlled data elements inside a data block that is returned anyway (e.g., sqlm_dbase) are zeroed. SQLMA_DBASE_TABLES Table activity information get snapshot for tables at the database level; the application on 'dbname' level for each application connected to the database; and the table level for each table that *was accessed* by an application connected to the database. THIS INFORMATION IS RETURNED ONLY IF THE DATABASE MONITOR TABLE SWITCH IS ON. REF REFID=XXXXXY SQLMA_DBASE_LOCKS Lock activity information at the get snapshot for locks on dbname database level, and the application level for each application connected to the database. Information is also returned for each lock that is held by an application. THIS INFORMATION IS RETURNED ONLY IF THE DATABASE MONITOR LOCK SWITCH IS ON. REF REFID=XXXXXY SQLMA_DBASE_TABLESPACES Information about tablespace activity get snapshot for tablespaces the database level; the application on 'dbname' level for each application connected to the database; and the tablespace level for each tablespace that has been accessed by an application connected to the database. This information is returned only if the Database Monitor BUFFERPOOL switch is ON. REF REFID=XXXXXY SQLMA_DBASE_APPLINFO Returns the same information as list applications for database dbname SQLMA_APPL_ALL (application identification information), but only for applications currently connected to the database specified for 'object'. To obtain information about a particular application: SQLMA_APPL Application level information for an get snapshot for application applid 'applid' application identified by application name, specified in 'object' Note: Application names can be listed by issuing an an SQLMA_APPLINFO_ALL, or SQLMA_DBASE_APPLINFO request. SQLMA_AGENT_ID Same as SQLMA_APPL, but the application is get snapshot for application specified by agent_id. The agent_id agentid 'agentid' can also be obtained from an SQLMA_APPLINFO_ALL or SQLMA_DBASE_APPLINFO request, or it may be obtained by issuing Operating System specific commands. For example, on AIX systems, the agentid is the process id of the db2agent process running on the server to service a connection and it can generally be obtained with the following command: 'ps -fu userid | grep db2agent' agent_id: The identifier of the agent to snapshot. Required only if obj_type is SQLMA_AGENT_ID, ignored otherwise. object: A null-terminated string that provides the database alias name (REF: List database directory.) if obj_type specifies one of the following requests: SQLMA_DBASE SQLMA_DBASE_APPLS SQLMA_DBASE_LOCKS SQLMA_DBASE_TABLESPACES SQLMA_DBASE_APPLINFO A null-terminated string that provides the application name (REF: List applications) if obj_type specifies SQLMA_APP It is ignored for all other requests. OUTPUT: The monitor data is returned in data blocks that are copied contiguously in the user provided buffer. The 'collected' output structure indicates the number of 'top-level' blocks that were copied to the buffer. The first 4 bytes of each block contain the size (as an unsigned int) of the block, the 5th byte is a char that indicates its type. The following table shows the blocks returned for each type of snapshot request. Input request type: Data block returned: block type: SQLMA_DBASE_APPLINFO sqlm_applinfo for each SQLM_APPLINFO_SS application connected to the database REF: sqlm_applinfo on page ... SQLMA_DB2 sqlm_db2 SQLM_DB2_SS SQLMA_APPLINFO_ALL sqlm_applinfo for each application connected to a database managed by the db2 instance. SQLMA_DCS_APPLINFO_ALL sqlm_dcs_applinfo for each dcb SQLM_DCS_APPLINFO_SS application. SQLMA_APPL_ALL sqlm_appl for each application SQLMA_DBASE_ALL sqlm_dbase for each database that SQLM_DBASE_SS has an active connection. SQLMA_DBASE sqlm_dbase SQLM_DBASE_SS SQLMA_DBASE_TABLES sqlm_table_header for the database SQLM_TABLE_HEADER_SS sqlm_table for each table accessed SQLM_TABLE_SS by an application connected to the database SQLMA_DBASE_LOCKS sqlm_dbase_lock for the database SQLM_DBASE_LOCK_SS sqlm_appl_lock for each app SQLM_APPL_LOCK_SS application connected to the database Following each sqlm_appl_lock, an SQLM_LOCK_SS sqlm_lock for each lock held by the application. SQLMA_DBASE_TABLESPACES sqlm_tablespace_header SQLM_TABLESPACE_HEADER_SS sqlm_tablespace for each SQLM_TABLESPACE_SS tablespace accessed by an application connected to the database SQLMA_DBASE_APPLINFO sqlm_applinfo for each SQLM_APPLINFO_SS application connected to the database SQLMA_APPL sqlm_appl SQLM_APPL_SS SQLMA_AGENT_ID sqlm_appl SQLM_APPL_SS See sqlmon.h for the declaration of each data block. collected: This output structure returns general information about the database manager; the status of the Database monitor switches; and the number of 'top-level' data blocks returned in the output buffer. size - size in bytes of sqlm_collected. Provided for binary compatibility when the DB2 server is not at the same level as the client (A down-level server may return a smaller sqlm_collected.) db2 - Set to 1 if the buffer contains an sqlm_db2 block. databases - number of sqlm_dbase returned in the buffer. table_databases - number of sqlm_table_header returned lock_databases - number of sqlm_dbase_lock returned. applications - number of sqlm_appl returned. applinfos - number of sqlm_applinfo returned. dcs_applinfos - number of sqlm_dcs_applinfo returned. tablespace_databases - number of sqlm_tablespace_header returned. server_db2_type - DB2 Server Type: SQLF_NT_STANDALONE Client/Server on same machine. SQLF_NT_SERVER Can be both client and server, both inbound and outbound. SQLF_NT_REQUESTOR Outbound only. Never returned. SQLF_NT_STAND_REQ Standalone requestor, can go outbound or have local connections. time_stamp - time at which Snapshot was taken. It is expressed as the number of seconds since Jan 1st, 1970 GMT, a form suitable for printing with ctime(). group_states - An array of sqlm_recording_group, one for each monitor switch: input_state: - Not applicable. Just ignore this field. output_state - The current state of the switch: 1 = ON, 0 = OFF start_time - A timestamp, the time a which the switch was turned ON, 0 if the switch is OFF. server_prdid - Product/version on server. A blank padded string of length SQLM_IDENT_SZ server_nname - Config NAME of server. A blank padded string of length SQLM_IDENT_SZ server_instance_name - DB2 instance name. A blank padded string of length SQLM_IDENT_SZ buffer_ptr: User provided buffer where to copy the Database Monitor data blocks. The order in which the blocks are returned is not guaranteed, and therefore you must check each block type (fifth byte) before reading it. There are two types of blocks: 'top-level' blocks, the number of which is indicated in the sqlm_collected output structure, and lower-level blocks, which are guaranteed to follow their parent block. Their number of lower-level block is indicated in the parent block. If the buffer is too small, data is truncated and sqlcode SQLM_RC_BUFFER_FULL is returned. For example, assuming the existance of a database that has 2 active connections, if the user requests SQLMA_DBASE_LOCKS, and SQLMA_DBASE. The following blocks may be returned in the buffer, (provided that the LOCK switch is ON): buffer: +---------------+--------------+---------+---------+--------------+---------+----------+ |sqlm_dbase_lock|sqlm_appl_lock|sqlm_lock|sqlm_lock|sqlm_appl_lock|sqlm_lock|sqlm_dbase| | num_appls: 2 | num_locks: 2| | | num_locks: 1 | | | +---------------+--------------+---------+---------+--------------+---------+----------+ Here, there are two 'top-level' structures: sqlm_dbase and sqlm_dbase_lock. sqlm_dbase_lock is followed by lower-level structures, which number is indicated in their parent structure. If the LOCK switch was OFF, the same request would return only the sqlm_dbase block: buffer: +------------+ | sqlm_dbase | | | +------------+ When a block returned contains data elements that are under switch control, which is the case for an sqlm_dbase, those elements are zeroed if their switch is OFF. *******************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include "sqlca.h" #include "sqlutil.h" #include "sqlmon.h" #include "util.h" #define CHECKERR(CE_STR) if (check_error (CE_STR, &sqlca) !=0) return 1; /****************************************************************************** * Print a Blank Padded String of maximum length SZ * * note: strings returned by sqlmonss are NOT NULL-TERMINATED, they are all * blank padded up to some maximum length. *******************************************************************************/ #define dump_BPSTRING(fp, str, SZ) { \ int k=0; \ while (str[k]!=' '&&k<SZ) k++; \ if (k<SZ) str[k]='\0'; \ fprintf(fp, #str": %0.*s\n", SZ, str); \ } int perform_db_snap (char *dbname, sqlm_collected *collected, char *buffer_ptr, int buffer_sz); /* Routines to assist in printing the output returned by "sqlmonss" */ char* appl_status_string(int val); char* lock_object_type_string(int val); char* lock_mode_string(int val); char* lock_status_string(int val); /* Printing routines. */ void dump_sqlm_dbase_lock(FILE* fp, sqlm_dbase_lock* db_lock); void dump_sqlm_appl_lock(FILE* fp, sqlm_appl_lock* appl_lock); void dump_sqlm_lock(FILE* fp, sqlm_lock* lock); /* Process the output from sqlmonss() */ void dump_snapshot_output(FILE* fp, sqlm_collected collected, char* snap); int main (int argc, char* argv[]) { struct sqlca sqlca; /* sqlmonsz() could be used to estimate required size */ sqlm_collected collected; char buffer_ptr[2048]; char dbname[9]; char userid[9]; char passwd[19]; char nodename[9]; if (argc == 5) { strcpy (userid, argv[2]); strcpy (passwd, argv[3]); strcpy (nodename, argv[4]); /*************************/ /* ATTACH API called */ /*************************/ sqleatin (nodename, userid, passwd, &sqlca); } else if (argc!=2) { printf ("\ndbsnap: Take a snapshot of database activity.\n"); printf ("\tUSAGE: dbsnap dbname [userid password remote_nodename]\n"); return 1; } strcpy (dbname, argv[1]); perform_db_snap(dbname, &collected, buffer_ptr, 2048); dump_snapshot_output(stdout, collected, buffer_ptr); return 0; } /****************************************************************************** * Perform a snapshot of lock activity for a database *******************************************************************************/ int perform_db_snap(char *dbname, sqlm_collected *collected, char *buffer_ptr, int buffer_sz) { int rc; struct sqlca sqlca; /* Request SQLMA_DBASE, and SQLMA_DBASE_LOCKS in the sqlma */ struct sqlma* sqlma = (struct sqlma *) malloc(SQLMASIZE(2)); sqlma->obj_num = 2; sqlma->obj_var[0].obj_type = SQLMA_DBASE; strcpy(sqlma->obj_var[0].object, dbname); sqlma->obj_var[1].obj_type = SQLMA_DBASE_LOCKS; strcpy(sqlma->obj_var[1].object, dbname); /*********************************************\ * DATABASE SYSTEM MONITOR SNAPSHOT API called * \*********************************************/ rc = sqlmonss(SQLM_DBMON_VERSION2, NULL, sqlma, buffer_sz, (void *) buffer_ptr, collected, &sqlca); CHECKERR ("SNAPSHOT"); free(sqlma); return rc; } /* end perform_db_snap */ /*----------------------------------------------------------------------------- The routines below are to assist in printing the output returned by sqlmonss. -----------------------------------------------------------------------------*/ /****************************************************************************** * Map Application Status to a printable string * * note: These #define may be found in sqlmon.h *******************************************************************************/ char* appl_status_string(int val) { switch (val) { case SQLM_CONNECTPEND: return "SQLM_CONNECTPEND"; case SQLM_CONNECTED: return "SQLM_CONNECTED"; case SQLM_UOWEXEC: return "SQLM_UOWEXEC"; case SQLM_UOWWAIT: return "SQLM_UOWWAIT"; case SQLM_LOCKWAIT: return "SQLM_LOCKWAIT"; case SQLM_COMMIT_ACT: return "SQLM_COMMIT_ACT"; case SQLM_ROLLBACK_ACT: return "SQLM_ROLLBACK_ACT"; case SQLM_RECOMP: return "SQLM_RECOMP"; case SQLM_COMP: return "SQLM_COMP"; case SQLM_INTR: return "SQLM_INTR"; case SQLM_DISCONNECTPEND: return "SQLM_DISCONNECTPEND"; case SQLM_TPREP: return "SQLM_TPREP"; case SQLM_THCOMT: return "SQLM_THCOMT"; case SQLM_THABRT: return "SQLM_THABRT"; case SQLM_TEND: return "SQLM_TEND"; case SQLM_CREATE_DB: return "SQLM_CREATE_DB"; case SQLM_RESTART: return "SQLM_RESTART"; case SQLM_RESTORE: return "SQLM_RESTORE"; case SQLM_BACKUP: return "SQLM_BACKUP"; case SQLM_LOAD: return "SQLM_LOAD"; case SQLM_UNLOAD: return "SQLM_UNLOAD"; case SQLM_IOERROR_WAIT: return "SQLM_IOERROR_WAIT"; case SQLM_QUIESCE_TABLESPACE: return "SQLM_QUIESCE_TABLESPACE"; } return ""; } /* end of appl_status_string */ /****************************************************************************** * Map lock_object_type to a printable string *******************************************************************************/ char* lock_object_type_string(int val) { switch (val) { case SQLM_TABLE_LOCK: return "SQLM_TABLE_LOCK"; case SQLM_ROW_LOCK: return "SQLM_ROW_LOCK"; case SQLM_INTERNAL_LOCK: return "SQLM_INTERNAL_LOCK"; case SQLM_TABLESPACE_LOCK: return "SQLM_TABLESPACE_LOCK"; case 0: return "No lock wait"; } return ""; } /* end of lock_object_type_string */ /****************************************************************************** * Map lock_mode to a printable string *******************************************************************************/ char* lock_mode_string(int val) { switch (val) { case SQLM_LNON: return "NO"; case SQLM_LOIS: return "IS"; case SQLM_LOIX: return "IX"; case SQLM_LOOS: return "S"; case SQLM_LSIX: return "SIX"; case SQLM_LOOX: return "X"; case SQLM_LOIN: return "IN"; case SQLM_LOOZ: return "Z"; case SQLM_LOOU: return "U"; } return ""; } /****************************************************************************** * Map lock_status to a printable string *******************************************************************************/ char* lock_status_string(int val) { switch (val) { case SQLM_LRBGRNT: return "Granted"; case SQLM_LRBCONV: return "Converting"; } return ""; } /*---------------------------------------------------------------------------- Printing routines. -----------------------------------------------------------------------------*/ /****************************************************************************** * Print an sqlm_dbase_lock *******************************************************************************/ void dump_sqlm_dbase_lock(FILE* fp, sqlm_dbase_lock* db_lock) { fprintf(fp,"\nsqlm_dbase_lock contains: \n"); fprintf(fp,"db_lock->info_type: %s\n", "SQLM_DBASE_LOCK_SS"); fprintf(fp,"db_lock->locks_held: %ld\n", db_lock->locks_held); fprintf(fp,"db_lock->appls_cur_cons: %ld\n", db_lock->appls_cur_cons); fprintf(fp,"db_lock->num_appls: %ld\n", db_lock->num_appls); fprintf(fp,"db_lock->locks_waiting: %ld\n", db_lock->locks_waiting); dump_BPSTRING(fp, db_lock->input_db_alias, SQLM_DBPATH_SZ); dump_BPSTRING(fp, db_lock->db_name, SQLM_IDENT_SZ); dump_BPSTRING(fp, db_lock->db_path, SQLM_DBPATH_SZ); } /* end of dump_sqlm_dbase_lock */ /****************************************************************************** * Print an sqlm_appl_lock *******************************************************************************/ void dump_sqlm_appl_lock(FILE* fp, sqlm_appl_lock* appl_lock) { fprintf(fp,"\nsqlm_appl_lock contains: \n"); fprintf(fp,"appl_lock->info_type: %s\n", "SQLM_APPL_LOCK_SS"); fprintf(fp,"appl_lock->agent_id: %6.6ld\n", appl_lock->agent_id); fprintf(fp,"appl_lock->appl_status: %s\n", appl_status_string(appl_lock->appl_status)); fprintf(fp,"appl_lock->codepage_id: %ld\n", appl_lock->codepage_id); fprintf(fp,"appl_lock->locks_held: %ld\n", appl_lock->locks_held); fprintf(fp,"appl_lock->num_locks: %ld\n", appl_lock->num_locks); /* Print the status change time, only if non-zero */ if (appl_lock->status_change_time.seconds) { fprintf(fp,"appl_lock->status_change_time: %s\n", ctime((time_t*) &appl_lock->status_change_time.seconds)); } /* end if status changed */ dump_BPSTRING(fp, appl_lock->appl_id, SQLM_APPLID_SZ); dump_BPSTRING(fp, appl_lock->sequence_no, SQLM_SEQ_SZ); dump_BPSTRING(fp, appl_lock->appl_name, SQLM_IDENT_SZ); dump_BPSTRING(fp, appl_lock->auth_id, SQLM_IDENT_SZ); dump_BPSTRING(fp, appl_lock->client_db_alias, SQLM_IDENT_SZ); /* The following information is returned only if the application is in a lock wait (otherwise it is zeroed, or set to blank spaces if a string) */ if (appl_lock->appl_status==SQLM_LOCKWAIT) { fprintf(fp,"appl_lock->lock_object_name: %ld\n", appl_lock->lock_object_name); fprintf(fp,"appl_lock->agent_id_holding_lk: %6.6ld\n", appl_lock->agent_id_holding_lk); fprintf(fp,"appl_lock->lock_object_type: %s\n", lock_object_type_string( appl_lock->lock_object_type)); fprintf(fp,"appl_lock->table_file_id: %ld\n", appl_lock->table_file_id); dump_BPSTRING(fp, appl_lock->appl_id_holding_lk, SQLM_APPLID_SZ); dump_BPSTRING(fp, appl_lock->sequence_no_holding_lk, SQLM_SEQ_SZ); dump_BPSTRING(fp, appl_lock->table_name, SQLM_IDENT_SZ); dump_BPSTRING(fp, appl_lock->table_schema, SQLM_IDENT_SZ); dump_BPSTRING(fp, appl_lock->tablespace_name, SQLM_IDENT_SZ); } /* end if this application is in a lock_wait */ } /* end of dump_sqlm_appl_lock */ /****************************************************************************** * Print an sqlm_lock *******************************************************************************/ void dump_sqlm_lock(FILE* fp, sqlm_lock* lock) { fprintf(fp,"\nsqlm_lock contains: \n"); fprintf(fp,"lock->info_type: %s\n", "SQLM_LOCK_SS"); fprintf(fp,"lock->lock_object_type: %s\n", lock_object_type_string(lock->lock_object_type)); /* Print the object of this lock */ switch (lock->lock_object_type) { case SQLM_ROW_LOCK: case SQLM_TABLE_LOCK: dump_BPSTRING(fp, lock->table_name, SQLM_IDENT_SZ); dump_BPSTRING(fp, lock->table_schema, SQLM_IDENT_SZ); fprintf(fp,"lock->table_file_id: %ld\n", lock->table_file_id); break; case SQLM_TABLESPACE_LOCK: dump_BPSTRING(fp, lock->tablespace_name, SQLM_IDENT_SZ); break; case SQLM_INTERNAL_LOCK: break; } fprintf(fp,"lock->lock_mode: %s\n", lock_mode_string(lock->lock_mode)); fprintf(fp,"lock->lock_status: %s\n",lock_status_string(lock->lock_status)); fprintf(fp,"lock->lock_object_name: %ld\n", lock->lock_object_name); } /* end of dump_sqlm_lock */ /*---------------------------------------------------------------------------- Process the output from sqlmonss() -----------------------------------------------------------------------------*/ /****************************************************************************** * Process the snapshot output - print it to file *******************************************************************************/ void dump_snapshot_output(FILE* fp, sqlm_collected collected, char* snap) { /* Compute the number of top-level data blocks returned */ int num_top_lvl_structs = collected.db2 + collected.databases + collected.table_databases + collected.lock_databases + collected.applications + collected.applinfos + collected.dcs_applinfos + collected.tablespace_databases; /* Process each block */ while (num_top_lvl_structs--) { /* Check the block type, (5th byte of any top-level block) */ switch ((unsigned char) *(snap+4)) { case SQLM_DB2_SS: { sqlm_db2* db2_snap = (sqlm_db2*) snap; /* ... dump_sqlm_db2(fp, db2_snap); */ snap+=db2_snap->size; } break; case SQLM_DBASE_SS: { sqlm_dbase* db_snap = (sqlm_dbase*) snap; /* ... dump_sqlm_dbase(fp, db_snap); */ snap+=db_snap->size; } break; case SQLM_APPL_SS: { sqlm_appl* appl_snap = (sqlm_appl*) snap; /* ... dump_sqlm_appl(fp, appl_snap); */ snap+=appl_snap->size; } break; case SQLM_TABLE_HEADER_SS: { int numtabs; sqlm_table_header* tabh_snap; tabh_snap=(sqlm_table_header*) snap; numtabs = tabh_snap->num_tables; /* ... dump_sqlm_table_header(fp, tabh_snap); */ snap+=tabh_snap->size; /* dump all table entries, which always immediately follow the header */ while (numtabs--) { sqlm_table* tab_snap; tab_snap = (sqlm_table*) snap; /* .. dump_sqlm_table(fp, tab_snap); */ snap+=tab_snap->size; } /* end of for each sqlm_table */ } break; case SQLM_DBASE_LOCK_SS: { int numaplocks; /* number of apps connected to this db */ sqlm_dbase_lock* dblock_snap = (sqlm_dbase_lock*) snap; dump_sqlm_dbase_lock(fp, dblock_snap); numaplocks = dblock_snap->num_appls; snap+=dblock_snap->size; /* dump all appl lock entries, which always follow the db entry */ while (numaplocks--) { sqlm_appl_lock* alock_snap; int numlocks; /* number of locks held by this application */ alock_snap = (sqlm_appl_lock*) snap; dump_sqlm_appl_lock(fp, alock_snap); numlocks=alock_snap->num_locks; snap+=alock_snap->size; /* dump all lock entries, which follow the appl entry */ while (numlocks--) { sqlm_lock* lock_snap; lock_snap = (sqlm_lock*) snap; dump_sqlm_lock(fp, lock_snap); snap+=lock_snap->size; } } } break; case SQLM_APPLINFO_SS: { sqlm_applinfo* ainfo_snap = (sqlm_applinfo*) snap; /* ... dump_sqlm_applinfo(fp, ainfo_snap); */ snap+=ainfo_snap->size; } break; case SQLM_DCS_APPLINFO_SS: { sqlm_dcs_applinfo* dcsainfo_snap; dcsainfo_snap = (sqlm_dcs_applinfo*) snap; /* ... dump_sqlm_dcs_applinfo(fp, dcsainfo_snap); */ snap+=dcsainfo_snap->size; } break; case SQLM_TABLESPACE_HEADER_SS: { sqlm_tablespace_header* tbh_snap=(sqlm_tablespace_header*) snap; int numtspaces; /* ... dump_sqlm_tablespace_header(fp, tbh_snap); */ numtspaces=tbh_snap->num_tablespaces; snap+=tbh_snap->size; while (numtspaces--) { sqlm_tablespace* ts_snap = (sqlm_tablespace*) snap; /* ... dump_sqlm_tablespace(fp, ts_snap); */ snap+=ts_snap->size; } } break; default: printf("%s:%d - %s\n", __FILE__, __LINE__, "Unexpected data in snapshot output buffer!"); } /* end switch on structure type */ } /* end while there are top-level structs in the snapshot output buffer */ } /* end of dump_snapshot_output */