/* Copyright © Oracle Corporation 1995. All Rights Reserved. */ /* MODULE: rdbsga_sample.c *++ * * Abstract: * Sample test program for Rdb implementation of Oracle/Rdb7 SGA API. * *-- */ /*****************************************************************************/ /* INCLUDE FILES */ /*****************************************************************************/ #include #include #include #include /*****************************************************************************/ /* INTERNAL DEFINITIONS */ /*****************************************************************************/ /* ** For convenience, declare some tables containing the tags for the info that ** we are going to request from the API. */ #define ARRAY_SIZE(_array) \ (sizeof(_array)/((char *) &_array[1] - (char *) &_array[0])) typedef enum { TEXT_TYPE = 1, /* string output */ INT_TYPE = 2, /* decimal output */ NODATA_TYPE = 3, /* no value displayed */ ADT_TYPE = 4, UNKNOWN_TYPE = 5, /* no value displayed */ HEX_TYPE = 6, /* hex output */ THRESH_TYPE = 7, /* threshold [%d,%d,%d]*/ RTPMS_TYPE = 8, ARPMS_TYPE = 9 } val_type_t; typedef struct tag_tab { ub2 tag; /* tag id for the requested info */ char *tagname; /* description for the info */ val_type_t val_type; /* type used to determine how to display info */ } tag_tab_t; tag_tab_t dbinfo_tab [] = { { RMUST_CT_DBINFO, "Database info class", NODATA_TYPE }, { RMUST_T_MAX_USER_CNT, "Max user count", INT_TYPE }, { RMUST_T_CREATE_DATE_TDT, "Creation date", TEXT_TYPE } }; tag_tab_t rtpms_tab [] = { { RMUST_CT_RTPMS_STATS, "RTPMS stats request", NODATA_TYPE }, { RMUST_T_RTPMS, "RTPMS stats", RTPMS_TYPE } }; tag_tab_t arpms_tab [] = { { RMUST_CT_ARPMS_STATS, "File I/O stats rqst", NODATA_TYPE }, { RMUST_T_DBID, "Storage area ID", INT_TYPE }, { RMUST_T_ARPMS, "ARPMS file I/O", ARPMS_TYPE } }; tag_tab_t fileinfo_tab [] = { { RMUST_CT_FILE, "File info request", INT_TYPE }, { RMUST_T_DBID, "Storage area ID", INT_TYPE }, { RMUST_T_STAREA_NAME, "Storage area name", TEXT_TYPE }, { RMUST_T_SNAPSHOT_FLG, "Is a snapshot area", INT_TYPE }, { RMUST_T_BACKUP_DATE_TDT,"Backup date", TEXT_TYPE } }; /* ** check_status () ** Check status and print error, exit on failure. */ static void check_status (kusst status); /* ** check_dbstatus () ** Check status and print error for database function. */ static void check_dbstatus (kusdb_handle db_handle, kusst status); /* ** get_data () ** Get data for a class */ static void get_data ( kusdb_handle db_handle, /* Handle to database connection */ tag_tab_t *tag_table, /* Table describing class and tags */ int table_size, /* Number of elements in tag table */ char *ret_buf, /* Pointer to return buffer */ int ret_buf_size, /* Size of return buffer */ int row_flag, /* TRUE if we want a single row */ int row_value); /* Value of row index if row_flag true */ /* ** dump_buf () ** Dump a buffer in hex */ static void dump_buf( char *hdr, int len, unsigned char *buf); /* ** find_index () ** Return the index into the tag table for a given tag. ** Return -1 if the tag is not found */ static int find_index ( ub2 tag, tag_tab_t *tag_table, int table_size); /*****************************************************************************/ /* main () */ /* Entry point for sample program. */ /*****************************************************************************/ main (int argc, char *argv[]) { kusdb_handle db_handle; char ret_buf [8192]; /* Return buffer */ char short_buf [300]; /* Short return buffer */ kusst status; int rtpms_tab_size = ARRAY_SIZE(rtpms_tab); int arpms_tab_size = ARRAY_SIZE(arpms_tab); int dbinfo_tab_size = ARRAY_SIZE(dbinfo_tab); int fileinfo_tab_size = ARRAY_SIZE(fileinfo_tab); if (argc < 2) { fputs ("USAGE: rdbsga_sample db_name\n", stderr); exit (1); } /* ** Attach to the database and format the request. */ check_status (kusdb_allocate(&db_handle)); status = kusdb_connect (db_handle, strlen(argv[1]), argv[1], 0, NULL); check_dbstatus(db_handle, status); /* ** Get some database info */ printf ("==============================================================\n"); printf ("= =\n"); printf ("= Class RMUST_CT_DBINFO =\n"); printf ("= =\n"); printf ("==============================================================\n"); get_data (db_handle, dbinfo_tab, dbinfo_tab_size, ret_buf, sizeof(ret_buf), FALSE, 0); /* ** Get file I/O info for one row. Specify that we want row 4, which ** corresponds to storage area 4. If we didn't specify only row 4, we ** would get data for all rows. */ printf ("==============================================================\n"); printf ("= =\n"); printf ("= Class RMUST_CT_ARPMS =\n"); printf ("= =\n"); printf ("==============================================================\n"); get_data (db_handle, arpms_tab, arpms_tab_size, ret_buf, sizeof(ret_buf), TRUE, 4); /* ** Get general stats data */ printf ("==============================================================\n"); printf ("= =\n"); printf ("= Class RMUST_CT_RTPMS =\n"); printf ("= =\n"); printf ("==============================================================\n"); get_data (db_handle, rtpms_tab, rtpms_tab_size, ret_buf, sizeof(ret_buf), FALSE, 0); /* ** Get info about storage areas. Since we aren't specifying that we want ** a specific row, data will be returned for all storage areas. Also, to ** demonstrate how buffer continuation works, specify a small return ** buffer. */ printf ("==============================================================\n"); printf ("= =\n"); printf ("= Class RMUST_CT_FILE =\n"); printf ("= =\n"); printf ("==============================================================\n"); get_data (db_handle, fileinfo_tab, fileinfo_tab_size, short_buf, sizeof(short_buf), FALSE, 0); /* ** Disconnect from the database */ check_status (kusdb_disconnect (db_handle)); check_status (kusdb_free (&db_handle)); } /* main () */ /*****************************************************************************/ /* check_status () */ /* Check status and print error on failure. */ /*****************************************************************************/ void check_status (kusst status) { if (status != KUSSTOK) { printf ("bad status %x\n", status); } } /****************************************************************************/ /* check_dbstatus () */ /* Check status and print error on failure in database calls */ /****************************************************************************/ void check_dbstatus (kusdb_handle db_handle, kusst status) { char message_buf [512]; ub4 outlen; if (status != KUSSTOK) { printf ("bad status %x\n", status); kusdb_error_text (db_handle, message_buf, sizeof(message_buf), &outlen); fprintf (stderr, "%.*s", outlen, message_buf); } } /*****************************************************************************/ /* dump_buf () */ /* Dump a buffer in hex */ /*****************************************************************************/ static void dump_buf(char *hdr, int len, unsigned char *buf) { int i; /* Loop index */ printf ("....... %s of length %02d characters .......\n", hdr == NULL ? "" : hdr, len); for (i = 0; i < len; i++) { printf (" %02X", buf [i] & 0xff); if ((i+1) % 20 == 0) putchar ('\n'); } if (i % 20) putchar ('\n'); } /* dump_buf () */ /****************************************************************************/ /* find_index () */ /* Return the index into the tag table for a given tag */ /* Return -1 if the tag is not found. */ /****************************************************************************/ static int find_index ( ub2 tag, /* tag to be found */ tag_tab_t *tag_table, /* tag table */ int table_size) /* size of tag table */ { int i; int index = -1; for (i = 0; i < table_size; i++) { if (tag_table[i].tag == tag) { index = i; break; } } return index; } /****************************************************************************/ /* get_data () */ /* Get data for a class */ /****************************************************************************/ void get_data ( kusdb_handle db_handle, /* Handle to database connection */ tag_tab_t *tag_table, /* Table describing class and tags */ int table_size, /* Number of elements in tag table */ char *ret_buf, /* Pointer to return buffer */ int ret_buf_size, /* Size of return buffer */ int row_flag, /* TRUE if we want a single row */ int row_value) /* Value of row index if row_flag true */ { unsigned char info_buf [512]; /* Info request buffer */ int info_buf_len; /* Size of actual data in info buf */ kustv_handle info_tlv, ret_tlv; int ret_buf_len; kustvs buf_term_status; kuscx_handle ctx_handle = NULL; ub2 tag, length; void *pvalue; int done_with_buffer; int more_data; int tab_index, i; kusst status; /* ** Allocate the TLV handles. */ ret_buf_len = ret_buf_size; check_status (kustv_allocate_handle (&ret_tlv, ret_buf, ret_buf_len)); check_status (kustv_allocate_handle (&info_tlv, info_buf, sizeof(info_buf))); /* ** Allocate the wildcard continuation context. This tells the API that if ** the return data is too long for the return buffer, we will call again to ** get more data. If we don't supply a context handle and the data is too ** much for the buffer, we will only get one buffer of data with a ** truncation tag at the end of the buffer. */ check_status (kuscx_allocate (&ctx_handle)); /* ** Build the request buffer for all tags in the tag table. ** If the caller requested a single row, put that value in with the class ** tag (the first tag in the table) */ if (row_flag) check_status (kustvp4_put_four_bytes (info_tlv, tag_table[0].tag, row_value)); else check_status (kustvptg_put_tag (info_tlv, tag_table[0].tag)); for (i = 1; i < table_size; i++) { check_status (kustvptg_put_tag(info_tlv,tag_table[i].tag)); } check_status (kustvptg_put_tag(info_tlv,KUSGTBEND)); check_status (kustv_offset (info_tlv, &info_buf_len)); /* ** Process and format the return buffer. */ more_data = TRUE; while (more_data) { /* ** Set up the return tlv handle for a request */ ret_buf_len = ret_buf_size; check_status (kustv_reinit_handle (ret_tlv, ret_buf, ret_buf_len)); /* ** Go get the data */ status = kusdb_get_info (db_handle, ctx_handle, info_buf, info_buf_len, ret_buf, &ret_buf_len, &buf_term_status); check_dbstatus (db_handle, status); if (status != KUSSTOK) more_data = FALSE; done_with_buffer = FALSE; while (!done_with_buffer && (status == KUSSTOK || status == KUSSTBINF)) { check_status (kustv_get (ret_tlv, &tag, &length, &pvalue)); switch (tag) { case KUSGTBOG: printf ("----- Beginning of group -----\n"); break; case KUSGTEOG: printf ("----- End of group -----\n"); break; case KUSGTBCNT: printf ("* Buffer continued *\n"); done_with_buffer = TRUE; break; case KUSGTBTRN: done_with_buffer = TRUE; more_data = FALSE; printf ("* Buffer truncated *\n"); break; case KUSGTBEND: printf ("* Buffer ended normally *\n"); done_with_buffer = TRUE; more_data = FALSE; break; default: /* ** print valid data items */ tab_index = find_index(tag, tag_table, table_size); if (tab_index >= 0) { switch (tag_table[tab_index].val_type) { case TEXT_TYPE: if (length > 0) { printf ("%s: %.*s\n", tag_table[tab_index].tagname, length, (char *)pvalue); } break; case INT_TYPE: printf ("%s: %d\n", tag_table[tab_index].tagname, *(int*)pvalue); break; case HEX_TYPE: printf ("%s: %x\n", tag_table[tab_index].tagname, *(int*)pvalue); break; case ADT_TYPE: printf ("%s: %08X %08X\n", tag_table[tab_index].tagname, *((int*)pvalue+1), *(int*)pvalue); break; case THRESH_TYPE: { unsigned char *t = (unsigned char *)pvalue; printf ("%s: [%d,%d,%d]\n", tag_table[tab_index].tagname, t[0], t[1], t[2]); break; } case RTPMS_TYPE: { ub4 *rtpms; rtpms = pvalue; printf ("%s root reads: %d\n", tag_table[tab_index].tagname, rtpms[RTPMS_FIOVECROOSYREAD]); break; } case ARPMS_TYPE: { FIOVEC_t *fiovec; fiovec = (FIOVEC_t *) pvalue; printf ("%s syread %d\n", tag_table[tab_index].tagname, fiovec->fiovecSyRead); break; } case NODATA_TYPE: case UNKNOWN_TYPE: printf ("%s\n", tag_table[tab_index].tagname); break; } } else { printf ("Bad tag [%d] encountered, length %d\n", *((int*)pvalue), length); dump_buf ("Value", length, (unsigned char *)pvalue); } } /* switch tag */ } /* while !done_with_buffer */ } /* while more data */ /* ** Free resources */ check_status (kuscx_free_handle (&ctx_handle)); check_status (kustv_free_handle (&info_tlv)); check_status (kustv_free_handle (&ret_tlv)); } /* test_get_one_class() */ /* End of file: rdbsga_sample.c */