/* Copyright © 2009, Oracle Corporation. All Rights Reserved. */ #pragma module rdb_stats_database "V7.2-31802" /* MODULE RDB_STATS_DATABASE *++ * Facility: Oracle Rdb * * Abstract: * Template example program showing one possible way to read * RMU/SHOW STATISTICS binary output data in real time or from * a file and store the data in a Rdb database. * * Author: * LASTOVICA * * Modification History: * * Version 7.2 * 5-AUG-09 31802 (NJL) Initial entry. *-- */ /* RDB_STATS_DATABASE - Convert binary statistics and store in database */ /* */ /* RDB_STATS_DATABASE is a sample C program that reads a RMU /SHOW */ /* STATISTICS binary file and converts all statistic values for each */ /* sample into the current rate per second. The statistics values in */ /* floating point format are then written to a database table called */ /* RMU$STATISTICS. The table RMU$STATISTICS will be created if it */ /* does not already exist in the output datbase. */ /* */ /* To use the RDB_STATS_DATABASE program create a foreign command */ /* symbol RDB_STATS_DATABASE to be */ /* "$disk:[dir]RDB_STATS_DATABASExx.EXE" and pass an output database */ /* and an input binary statistics file name. */ /* */ /* $ RDB_STATS_DATABASE == "$SYS$LOGIN:RDB_STATS_DATABASE72;" */ /* $ RMU /SHOW STATISTICS MFP - */ /* /NOINTERACTIVE - */ /* /OUTPUT = 2000-11-16-00-56.STATS - */ /* /UNTIL = "16-NOV-2000 23:59:00" - */ /* /TIME = 60 */ /* $ RDB_STATS_DATABASE MYSTATS.RDB 2000-11-16-00-56.STATS */ /* */ /* It is also possible to create a VMS mailbox and collect and record */ /* the statistics in real time. To do this, use two processes and */ /* have one run RMU /SHOW STATISTICS and output to a mailbox and have */ /* the other read from the mailbox and store in a database. In such a */ /* configuration it likely makes sense to set records_per_txn to 1 so */ /* that each record insert is followed by a commit. */ /* */ /* The statistics information can be stored in any Rdb database */ /* (either the the dtabse that statistics are being gathered for or */ /* another). */ /* */ /* Compile and link: */ /* */ /* $ DEFINE RDMS_BUILD_DB */ /* $ SQL$MOD RDB_STATS_DATABASE_SQL1_72.SQLMOD */ /* $ SQL$MOD RDB_STATS_DATABASE_SQL2_72.SQLMOD */ /* $ CC RDB_STATS_DATABASE72 */ /* $ LINK RDB_STATS_DATABASE72 +- */ /* RDB_STATS_DATABASE_SQL1_72 + - */ /* RDB_STATS_DATABASE_SQL2_72 +- */ /* SQL$USER /LIBRARY */ /* */ /* This example is intended solely and simply to be used as a template */ /* for writing your own program. */ /* */ /* Oracle Corporation assumes no responsibility for the use of this */ /* example program. Oracle Corporation reserves the right to change the */ /* format and contents of the Oracle Rdb RMU SHOW STATISTICS binary */ /* output file at any time without prior notice. No support for this */ /* example template program is expressed or implied. */ #include #include #include #include #define records_per_txn 250 // number of records per transaction #define stattype __int64 #define headerfiller 7676 #define MAX_FIELD 1023 void create_table(); void sql_signal(); void insert_stats(); void commit_transaction(); #pragma member_alignment save /* save the current alignment */ #pragma nomember_alignment /* force no alignment of struct members */ typedef struct stats_hr_str { /* statistics file header */ __int64 start_tad; /* database open date/time */ int maj_ver; /* major version of structures */ int min_ver; /* minor version of structures */ int flags; /* statistics flags */ int arpms_cnt; /* by-area count */ int arpms_size; /* by-area struct size (bytes) */ int arpms_rsz; /* by-area record size (bytes) */ int arpms_rct; /* by-area record count */ int arpms_per_rsz; /* # of arpms per by-area record */ int filid_cnt; /* filid count (same as arpms_cnt */ int filid_size; /* filid struct size (bytes) */ int filid_rsz; /* filid record size (bytes) */ int filid_rct; /* filid record count */ int filid_per_rsz; /* # of filid per arpms record */ int rcache_cnt; /* rcache count (same as rcpms_c` */ int rcache_size; /* rcache struct size (bytes) */ int rcache_rsz; /* rcache record size (bytes) */ int rcache_rct; /* rcache record count */ int rcache_per_rsz; /* # of rcache per rcpms record */ int rcpms_cnt; /* by-rcache count */ int rcpms_size; /* by-rcache struct size (bytes) */ int rcpms_rsz; /* by-rcache record size (bytes) */ int rcpms_rct; /* by-rcache record count */ int rcpms_per_rsz; /* # of rcpms per by-rcache reco` */ int lapms_cnt; /* by-area count */ int lapms_size; /* by-area struct size (bytes) */ int lapms_rsz; /* by-area record size (bytes) */ int lapms_rct; /* by-area record count */ int lapms_per_rsz; /* # of lapms per by-area record */ int max_user_cnt; /* max # of users (from kroot) */ int max_node_cnt; /* max # of nodes (from kroot) */ char ascic_node[65]; /* node name length counted string */ char filler0[63]; /* filler space */ char rt_filnam[256]; /* database root file counted string */ int monitor_pid; /* process being monitored */ char filler1[headerfiller]; /* filler space */ } stats_hr; typedef struct stats_vec_int_str { /* statistics data structure */ __int64 RT_START_TAD; /* as read from the input */ stattype RT [MAX_FIELD]; /* file; data values are int. */ } stats_vec_int; typedef struct stats_vec_nam_str { /* statistic field names */ char *field [1023]; } stats_vec_nam; #pragma member_alignment restore /* restore alignment */ int main (int argc, char *argv[]) { char nodename[255]; /* node name from input file */ float rate[MAX_FIELD]; /* rate between samples */ float delta_time; /* seconds between samples */ FILE *ifile; /* input file handle */ stats_hr hr; /* header record */ stats_vec_int sv; /* 'current' statistics vector */ stats_vec_int last_sv; /* 'prior' statistics vector */ int sqlcode = 0; /* sqlcode */ int txn = 0; /* number of records added in txn */ if (argc != 3) /* database and input required */ { printf ("Usage: %s \n", argv[0]); return -1; } ifile = fopen ( argv[2], "rb", "rop=rah", "mbf=8", "mbc=124"); if (ifile == NULL) { perror ("Error opening input file"); return -1; } /* create a new RMU$STATISTICS table if it does not already exist */ create_table(&sqlcode, argv[1]); if ((sqlcode != SQLCODE_TBLEXISTS) && (sqlcode)) sql_signal(); commit_transaction(&sqlcode, argv[1]); if (sqlcode) sql_signal(); /* read the input statistics file header record. then read the */ /* next one to use as the "last" sample. */ fread (&hr, sizeof(hr), 1, ifile); printf ("database %s on node %s \n", &hr.rt_filnam[1], &hr.ascic_node[1]); printf ("max users=%d, max nodes=%d, areas=%d, max logical areas=%d\n", hr.max_user_cnt, hr.max_node_cnt, hr.arpms_cnt, hr.lapms_cnt); memset (&nodename, 0, sizeof(nodename)); memcpy (&nodename,&hr.ascic_node[1],hr.ascic_node[0]); fread (&last_sv, sizeof(last_sv), 1, ifile); /* initial sample */ /* read and process one record at a time from the input file. capture */ /* date/time of each sample and determine a delta and convert values to */ /* rates per second. */ while (fread (&sv, sizeof(sv), 1, ifile)) { delta_time = sv.RT_START_TAD - last_sv.RT_START_TAD; delta_time = delta_time / 10000000.0; for (int i=0; i<= MAX_FIELD; i++) rate[i] = ((float) (sv.RT[i] - last_sv.RT[i])) / delta_time; insert_stats(&sqlcode, argv[1], &nodename, &sv.RT_START_TAD, &rate); if (sqlcode) sql_signal(); if (++txn > records_per_txn) { commit_transaction(&sqlcode, argv[1]); if (sqlcode) sql_signal(); txn = 0; } memcpy (&last_sv, &sv, sizeof(sv)); /* current -> prior */ } if (txn) { commit_transaction(&sqlcode, argv[1]); if (sqlcode) sql_signal(); } fclose (ifile); return 0; }