[Orca-checkins] r391 - in trunk/orca: data_gatherers/orcallator lib/SE/3.3.1

dmberezin at hotmail.com dmberezin at hotmail.com
Tue Sep 14 11:28:56 PDT 2004


Author: dmberezin at hotmail.com
Date: Tue Sep 14 11:27:02 2004
New Revision: 391

Added:
   trunk/orca/lib/SE/3.3.1/tapeinfo.se
Modified:
   trunk/orca/data_gatherers/orcallator/orcallator.se
Log:
The first update to the disk/tape data collection on Solaris.

* lib/SE/3.3.1/tapeinfo.se
  New file, based on diskinfo.se that is included in SE Toolkit.
* data_gatherers/orcallator/orcallator.se
  Naming conventions are changed from RAW_disk to KSTAT_IO
  Static RAW_disk array is replaced by dynamic ORCA_io_dev_info array
  (struct RawDisk): Renamed to struct io_dev_info_t
  (raw_disk_update): Renamed to orca_io_info_update
  (struct io_dev_info_t): long_name and short_name are now strings, thus dynamic
  (orca_io_info_update): Removed some unused variables:
    update
    delta
    time_update
    time_void
    short_name
  (raw_disk_short_name_cmp and raw_disk_map): Removed. Replaced by name lookup
  using find_inst
  Added tape long name mapping (stxxx is being mapped to rmt/xx) support. This
  requires tapeinfo.se (modified version of diskinfo.se)
  The following global variables are removed:
    RAW_disk_map
    RAW_disk_count
    RAW_disk_lastupdate


Modified: trunk/orca/data_gatherers/orcallator/orcallator.se
==============================================================================
--- trunk/orca/data_gatherers/orcallator/orcallator.se	(original)
+++ trunk/orca/data_gatherers/orcallator/orcallator.se	Tue Sep 14 11:27:02 2004
@@ -23,8 +23,8 @@
 // The maximum number of columns of data.
 #define MAX_COLUMNS		2048
 
-// Enable the raw disk measuring code.
-#define USE_RAWDISK		1
+// Enable kstat io measuring code.
+#define USE_KSTAT_IO		1
 
 // If WATCH_OS is defined, then measure every part of the operating
 // system.
@@ -297,8 +297,9 @@
 
 #endif
 
-#ifdef USE_RAWDISK
+#ifdef USE_KSTAT_IO
 #include <sys_kstat.se>
+#include <tapeinfo.se>
 // This code was developed so that the performance of virtual disks
 // originating from a Sun A1000 raid controller could be monitored.
 // These disks do not show up in the GLOBAL_disk[] io structure of SE.
@@ -306,10 +307,10 @@
 // This extension accesses the sys_kstat.se interface to the kstat IO
 // queues to extract info on drives not available in the kstat.se
 // kstat$disk interface.  Global data shared between function calls.
-struct RawDisk {
+struct io_dev_info_t {
   // Exposed interface that matches kstat.
-  char		long_name[48];
-  char		short_name[8];
+  string	long_name;
+  string	short_name;
   double	reads;
   double	kreads;
   double	writes;
@@ -337,124 +338,13 @@
 };
 
 // Define global for tracking raw disk data.
-#ifndef MAX_RAWDISKS
-#define MAX_RAWDISKS	1024
-#endif
-
-RawDisk			RAW_disk[MAX_RAWDISKS];
-int			RAW_disk_map=0;
-int			RAW_disk_count=0;
-double			RAW_disk_lastupdate;
-
-// Compare two short disk names and return if they have on the same
-// physical device name, ignoring slice info.
-int raw_disk_short_name_cmp(char disk1[],
-                            int  disk1_length,
-                            char disk2[],
-                            int  disk2_length)
-{
-  int i;
-
-  // Handle dad disks first since they do not have commas.
-  if (strncmp("dad", disk1, 3) == 0) {
-    return strncmp(disk1, disk2, disk1_length);
-  }
-
-  // Extract the physical disk name from disk slices.  This only works
-  // with SCSI disks where slices have commma separators.
-  for (i=0; i<disk1_length; ++i) {
-    if (disk1[i] == ',') {
-      disk1_length = i;
-      break;
-    }
-  }
-  for (i=0; i<disk2_length; ++i) {
-    if (disk2[i] == ',') {
-      disk2_length = i;
-      break;
-    }
-  }
-  if (disk1_length != disk2_length) {
-    return 1;
-  }
-  return strncmp(disk1, disk2, disk1_length);
-}
-
-// Function to scan kstat and map short device names to long device names.
-raw_disk_map() {
-  int  first_name_length;
-  char first_name[16];
-  int  second_name_length;
-  char second_name[16];
-  char long_name[16];
-  char short_name[16];
-  int  short_name_length;
-  int  i;
-  int  j;
-
-  // This section is used to map short names to long names.  Since
-  // raw_disk_update has already identified how many physical devices
-  // it simply tries to find theses devices in GLOBAL_disk_info[].
-  //
-  // SE appears to have a bug where GLOBAL_diskinfo_size can be larger
-  // than the number of entries in GLOBAL_disk_info[] under a variety
-  // of conditions.  In later versions of SE GLOBAL_diskinfo_size has
-  // been removed.  This appears to fix the above problem.  This code
-  // uses MAX_RAWDISKS for the table length and the assumption that
-  // short disks names come before short disk partition names to
-  // detect the end of the table.  If it fails to detect the end it
-  // will core dump when it addresses unallocated memory.
-  //
-  // These symbols are used to recognize when we slip past the end of
-  // the raw devices in GLOBAL_disk_info.  It would be nice to just
-  // look for a slice like sd0,a but unfortunately EIDE disks do not
-  // have slices.
-  //
-  // Check for the first and second disk in case the CD-ROM shows up
-  // as the first disk since it will not show slice information unless
-  // it is mounted.
-  strcpy(first_name, GLOBAL_disk_info[0].short_name);
-  first_name_length = strlen(first_name);
-  if (MAX_RAWDISKS > 1) {
-    strcpy(second_name, GLOBAL_disk_info[1].short_name);
-    second_name_length = strlen(second_name);
-  }
-  for (i=0; i<RAW_disk_count; ++i) {
-    // Do not map st & fd devices.
-    if (strncmp(RAW_disk[i].short_name, "st", 2) != 0 &&
-        strncmp(RAW_disk[i].short_name, "fd", 2) != 0) {
-      for (j=0; j<MAX_RAWDISKS; ++j) {
-        strcpy(short_name, GLOBAL_disk_info[j].short_name);
-        if (j > 0) {
-          short_name_length = strlen(short_name);
-          if (raw_disk_short_name_cmp(first_name,
-                                      first_name_length,
-                                      short_name,
-                                      short_name_length) == 0) {
-            break;
-          }
-          if (j > 1) {
-            if (raw_disk_short_name_cmp(second_name,
-                                        second_name_length,
-                                        short_name,
-                                        short_name_length) == 0) {
-              break;
-            }
-          }
-        }
-        if (strcmp(RAW_disk[i].short_name, short_name) == 0) {
-          strcpy(long_name, GLOBAL_disk_info[j].long_name);
-          strcpy(RAW_disk[i].long_name, long_name);
-          break;
-        }
-      }
-    }
-  }
-  RAW_disk_map = 0;
-}
-
-raw_disk_update() {
-  int         rdisk;
+io_dev_info_t	ORCA_io_dev_info[];
+int		ORCA_io_dev_count=0;
+int		ORCA_max_io_dev_count=0;
+
+orca_io_info_update() {
+  int		iodev;
+  int		index;
   ulong       ul;
   kstat_ctl_t kc[1];
   kstat_t     kp[1];
@@ -478,21 +368,11 @@
   double      elapsed_etime;
   double      hz_etime;
   double      nanosecond = NANOSEC;
-  double      update;
-  double      delta;
-  timeval_t   time_update[1];
-  ulong       time_void;
-  char        short_name[8];
-
-  gettimeofday(time_update, time_void);
-  update = time_update[0].tv_sec + (time_update[0].tv_usec / 1000000.0);
-  delta  = update - RAW_disk_lastupdate;
-  RAW_disk_lastupdate = update;
 
   kc[0] = kstat_open();
   // Read them.
   if (kstat_read(kc, kp, 0) == -1) {
-    perror("raw_disk_update:kstat_read");
+    perror("orca_io_info_update:kstat_read");
     exit(1);
   }
 
@@ -500,40 +380,55 @@
   for (ul=kc[0].kc_chain; ul !=0; ul=nkp[0].ks_next) {
     struct_fill(nkp[0], ul);
     if (nkp[0].ks_type == KSTAT_TYPE_IO) {
-      strcpy(short_name, nkp[0].ks_name);
-      if (short_name[0] != 'm' &&
-          short_name[0] != 'n' &&
-          strchr(short_name,',') == nil) {
+      // Look for disk or tape statistics
+      if (nkp[0].ks_class == "disk" || nkp[0].ks_class == "tape") {
         // Try to locate device.
-        for (rdisk=0; rdisk<RAW_disk_count; ++rdisk) {
-          if (strcmp(RAW_disk[rdisk].short_name, short_name) == 0) {
+        for (iodev=0; iodev < ORCA_io_dev_count; ++iodev) {
+          if (ORCA_io_dev_info[iodev].short_name == nkp[0].ks_name) {
             break;
           }
         }
 
-        // It must be new.  Add it!
-        if (rdisk == RAW_disk_count) {
-          // Must be a tape drive or something else.  Schedule device
-          // name map cycle.
-          RAW_disk_map = 1;
-          strcpy(RAW_disk[rdisk].long_name, short_name);
-          strcpy(RAW_disk[rdisk].short_name, short_name);
-          RAW_disk[rdisk]._reads       = 0;
-          RAW_disk[rdisk]._nread       = 0;
-          RAW_disk[rdisk]._rlentime    = 0;
-          RAW_disk[rdisk]._rlastupdate = boot_time;
-          RAW_disk[rdisk]._rcnt        = 0;
-          RAW_disk[rdisk]._writes      = 0;
-          RAW_disk[rdisk]._nwritten    = 0;
-          RAW_disk[rdisk]._wlentime    = 0;
-          RAW_disk[rdisk]._wlastupdate = boot_time;
-          RAW_disk[rdisk]._wcnt        = 0;
-          RAW_disk_count++;
+        // It must be new. Add it!
+        if (iodev == ORCA_io_dev_count) {
+          // Grow the device array if needed
+          if (ORCA_io_dev_count == ORCA_max_io_dev_count) {
+            ORCA_max_io_dev_count += 10;
+            ORCA_io_dev_info = renew ORCA_io_dev_info[ORCA_max_io_dev_count];
+          }
+
+          if (nkp[0].ks_class == "tape") {
+            index = find_tape_inst(nkp[0].ks_name);
+          } else {
+            index = find_inst(nkp[0].ks_name);
+          }
+          if (index != -1) {
+            if (nkp[0].ks_class == "tape") {
+              ORCA_io_dev_info[iodev].long_name = GLOBAL_tape_info[index].long_name;
+            } else {
+              ORCA_io_dev_info[iodev].long_name = GLOBAL_disk_info[index].long_name;
+            }
+          } else {
+            ORCA_io_dev_info[iodev].long_name = nkp[0].ks_name;
+          }
+          ORCA_io_dev_info[iodev].short_name = nkp[0].ks_name;
+
+          ORCA_io_dev_info[iodev]._reads       = 0;
+          ORCA_io_dev_info[iodev]._nread       = 0;
+          ORCA_io_dev_info[iodev]._rlentime    = 0;
+          ORCA_io_dev_info[iodev]._rlastupdate = boot_time;
+          ORCA_io_dev_info[iodev]._rcnt        = 0;
+          ORCA_io_dev_info[iodev]._writes      = 0;
+          ORCA_io_dev_info[iodev]._nwritten    = 0;
+          ORCA_io_dev_info[iodev]._wlentime    = 0;
+          ORCA_io_dev_info[iodev]._wlastupdate = boot_time;
+          ORCA_io_dev_info[iodev]._wcnt        = 0;
+          ORCA_io_dev_count++;
         }
 
         // Update the device registers.
         if (kstat_read(kc, nkp, 0) == -1) {
-          perror("raw_disk_update:kstat_read error");
+          perror("orca_io_info_update:kstat_read error");
           exit(1);
         } else {
           // Read sys_kstat device IO queue to find out about recent
@@ -546,32 +441,33 @@
           // the error forces the IOs to get attributed to the next IO
           // cycle.
           struct_fill(kio, nkp[0].ks_data);
+
           _nread  =  kio.nread;
-          if (RAW_disk[rdisk]._nread > _nread) {
-            _nread = RAW_disk[rdisk]._nread;
+          if (ORCA_io_dev_info[iodev]._nread > _nread) {
+            _nread = ORCA_io_dev_info[iodev]._nread;
           }
           _reads = kio.reads;
-	  if (RAW_disk[rdisk]._reads > _reads) {
-            _reads = RAW_disk[rdisk]._reads;
+	  if (ORCA_io_dev_info[iodev]._reads > _reads) {
+            _reads = ORCA_io_dev_info[iodev]._reads;
           }
           _rlentime    = kio.rlentime;
           _rtime       = kio.rtime;
           _rlastupdate = kio.wlastupdate;
           _rcnt        = kio.rcnt;
           _nwritten    = kio.nwritten;
-          if (RAW_disk[rdisk]._nwritten > _nwritten) {
-            _nwritten = RAW_disk[rdisk]._nwritten;
+          if (ORCA_io_dev_info[iodev]._nwritten > _nwritten) {
+            _nwritten = ORCA_io_dev_info[iodev]._nwritten;
           }
           _writes = kio.writes;
-          if (RAW_disk[rdisk]._writes > _writes) {
-            _writes = RAW_disk[rdisk]._nwritten;
+          if (ORCA_io_dev_info[iodev]._writes > _writes) {
+            _writes = ORCA_io_dev_info[iodev]._nwritten;
           }
           _wlentime    = kio.wlentime;
           _wtime       = kio.wtime;
           _wlastupdate = kio.wlastupdate;
           _wcnt        = kio.wcnt;
 
-          elapsed_etime = (_wlastupdate - RAW_disk[rdisk]._wlastupdate);
+          elapsed_etime = (_wlastupdate - ORCA_io_dev_info[iodev]._wlastupdate);
           if (elapsed_etime > 0)  {
             hz_etime = elapsed_etime / nanosecond;
             big_etime = 1024.0 * hz_etime;
@@ -580,50 +476,44 @@
             hz_etime = 1.0;
             big_etime = 1024.0;
           }
-          RAW_disk[rdisk].reads  =(_reads-RAW_disk[rdisk]._reads)  /hz_etime;
-          RAW_disk[rdisk].kreads =(_nread-RAW_disk[rdisk]._nread)  /big_etime;
-          RAW_disk[rdisk].writes =(_writes-RAW_disk[rdisk]._writes)/hz_etime;
-          RAW_disk[rdisk].kwrites=(_nwritten-RAW_disk[rdisk]._nwritten) / big_etime;
+          ORCA_io_dev_info[iodev].reads  =(_reads-ORCA_io_dev_info[iodev]._reads)  /hz_etime;
+          ORCA_io_dev_info[iodev].kreads =(_nread-ORCA_io_dev_info[iodev]._nread)  /big_etime;
+          ORCA_io_dev_info[iodev].writes =(_writes-ORCA_io_dev_info[iodev]._writes)/hz_etime;
+          ORCA_io_dev_info[iodev].kwrites=(_nwritten-ORCA_io_dev_info[iodev]._nwritten) / big_etime;
 
-          read_writes = elapsed_etime * (RAW_disk[rdisk].reads + RAW_disk[rdisk].writes) / 1024.0;
+          read_writes = elapsed_etime * (ORCA_io_dev_info[iodev].reads + ORCA_io_dev_info[iodev].writes) / 1024.0;
           if (read_writes > 0) {
-            RAW_disk[rdisk].avg_wait = (_wlentime - RAW_disk[rdisk]._wlentime) / read_writes;
-            RAW_disk[rdisk].avg_serv = (_rlentime - RAW_disk[rdisk]._rlentime) / read_writes;
-            RAW_disk[rdisk].service  = RAW_disk[rdisk].avg_wait + RAW_disk[rdisk].avg_serv;
+            ORCA_io_dev_info[iodev].avg_wait = (_wlentime - ORCA_io_dev_info[iodev]._wlentime) / read_writes;
+            ORCA_io_dev_info[iodev].avg_serv = (_rlentime - ORCA_io_dev_info[iodev]._rlentime) / read_writes;
+            ORCA_io_dev_info[iodev].service  = ORCA_io_dev_info[iodev].avg_wait + ORCA_io_dev_info[iodev].avg_serv;
           } else {
-            RAW_disk[rdisk].avg_wait = 0.0;
-            RAW_disk[rdisk].avg_serv = 0.0;
-            RAW_disk[rdisk].service  = 0.0;
+            ORCA_io_dev_info[iodev].avg_wait = 0.0;
+            ORCA_io_dev_info[iodev].avg_serv = 0.0;
+            ORCA_io_dev_info[iodev].service  = 0.0;
           }
 
           // Update the counters.
-          RAW_disk[rdisk].run_percent  = 100.0 * (_rtime  - RAW_disk[rdisk]._rtime) / elapsed_etime;
-          RAW_disk[rdisk].wait_percent = 100.0 * (_wtime - RAW_disk[rdisk]._wtime) / elapsed_etime;
-          RAW_disk[rdisk]._writes      = _writes;
-          RAW_disk[rdisk]._nwritten    = _nwritten;
-          RAW_disk[rdisk]._wlastupdate = _wlastupdate;
-          RAW_disk[rdisk]._wlentime    = _wlentime;
-          RAW_disk[rdisk]._wtime       = _wtime;
-          RAW_disk[rdisk]._wcnt        = _wcnt;
-          RAW_disk[rdisk]._reads       = _reads;
-          RAW_disk[rdisk]._nread       = _nread;
-          RAW_disk[rdisk]._rlastupdate = _rlastupdate;
-          RAW_disk[rdisk]._rlentime    = _rlentime;
-          RAW_disk[rdisk]._rtime       = _rtime;
-          RAW_disk[rdisk]._rcnt        = _rcnt;
+          ORCA_io_dev_info[iodev].run_percent  = 100.0 * (_rtime  - ORCA_io_dev_info[iodev]._rtime) / elapsed_etime;
+          ORCA_io_dev_info[iodev].wait_percent = 100.0 * (_wtime - ORCA_io_dev_info[iodev]._wtime) / elapsed_etime;
+          ORCA_io_dev_info[iodev]._writes      = _writes;
+          ORCA_io_dev_info[iodev]._nwritten    = _nwritten;
+          ORCA_io_dev_info[iodev]._wlastupdate = _wlastupdate;
+          ORCA_io_dev_info[iodev]._wlentime    = _wlentime;
+          ORCA_io_dev_info[iodev]._wtime       = _wtime;
+          ORCA_io_dev_info[iodev]._wcnt        = _wcnt;
+          ORCA_io_dev_info[iodev]._reads       = _reads;
+          ORCA_io_dev_info[iodev]._nread       = _nread;
+          ORCA_io_dev_info[iodev]._rlastupdate = _rlastupdate;
+          ORCA_io_dev_info[iodev]._rlentime    = _rlentime;
+          ORCA_io_dev_info[iodev]._rtime       = _rtime;
+          ORCA_io_dev_info[iodev]._rcnt        = _rcnt;
         }
       }
     }
   }
   kstat_close(kc);
-
-  // Map long device names for any drives that we just discovered.
-  if (RAW_disk_map == 1) {
-    raw_disk_map();
-  }
 }
-#endif
-// RAWDISK
+#endif // USE_KSTAT_IO
 
 // Variables for handling output.
 string		compress = getenv("COMPRESSOR"); // How to compress logs.
@@ -1025,8 +915,8 @@
   tmp_tcp           = tcp$tcp;
 #endif
 
-#ifdef USE_RAWDISK
-   raw_disk_update();
+#ifdef USE_KSTAT_IO
+   orca_io_info_update();
 #endif
 }
 
@@ -1598,29 +1488,29 @@
   total_tape_writek   = 0.0;
   tape_count          = 0;
 
-#ifdef USE_RAWDISK
-  for (i=0; i<RAW_disk_count; ++i) {
+#ifdef USE_KSTAT_IO
+  for (i=0; i<ORCA_io_dev_count; ++i) {
     // Record tape drive st devices differently than regular disk devices.
-    if (RAW_disk[i].short_name[0] == 's' && RAW_disk[i].short_name[1] == 't') {
+    if (ORCA_io_dev_info[i].short_name =~ "^st.*") {
       tape_count++;
-      total_tape_reads  += RAW_disk[i].reads;
-      total_tape_writes += RAW_disk[i].writes;
-      total_tape_readk  += RAW_disk[i].kreads;
-      total_tape_writek += RAW_disk[i].kwrites;
-      put_output(sprintf("tape_runp_%s", RAW_disk[i].long_name),
-                 sprintf("%16.5f", RAW_disk[i].run_percent));
+      total_tape_reads  += ORCA_io_dev_info[i].reads;
+      total_tape_writes += ORCA_io_dev_info[i].writes;
+      total_tape_readk  += ORCA_io_dev_info[i].kreads;
+      total_tape_writek += ORCA_io_dev_info[i].kwrites;
+      put_output(sprintf("tape_runp_%s", ORCA_io_dev_info[i].long_name),
+                 sprintf("%16.5f", ORCA_io_dev_info[i].run_percent));
       continue;
     }
     // Block the listing of floppy drives for now.
-    if (RAW_disk[i].short_name[0] == 'f' && RAW_disk[i].short_name[1] == 'd') {
+    if (ORCA_io_dev_info[i].short_name =~ "^fd.*") {
       continue;
     }
     disk_count++;
-    put_output(sprintf("disk_runp_%s", RAW_disk[i].long_name),
-               sprintf("%16.5f", RAW_disk[i].run_percent));
+    put_output(sprintf("disk_runp_%s", ORCA_io_dev_info[i].long_name),
+               sprintf("%16.5f", ORCA_io_dev_info[i].run_percent));
 
-    put_output(sprintf("disk_svct_%s", RAW_disk[i].long_name),
-               sprintf("%16.5f", RAW_disk[i].service));
+    put_output(sprintf("disk_svct_%s", ORCA_io_dev_info[i].long_name),
+               sprintf("%16.5f", ORCA_io_dev_info[i].service));
 
     // Comments from Damon Atkins <Damon.Atkins at nabaus.com.au>.  Check
     // [wr]lentime to see if an EMC is using a fake disk for control.
@@ -1637,13 +1527,13 @@
 #ifdef HAVE_EMC_DISK_CONTROL
     if ((pioGLOB_old_wlentime[i] + pioGLOB_old_rlentime[i]) > 1) {
 #endif
-      total_disk_reads  += RAW_disk[i].reads;
-      total_disk_writes += RAW_disk[i].writes;
-      total_disk_readk  += RAW_disk[i].kreads;
-      total_disk_writek += RAW_disk[i].kwrites;
-      mean_disk_busy    += RAW_disk[i].run_percent;
-      if (RAW_disk[i].run_percent > peak_disk_busy) {
-         peak_disk_busy = RAW_disk[i].run_percent;
+      total_disk_reads  += ORCA_io_dev_info[i].reads;
+      total_disk_writes += ORCA_io_dev_info[i].writes;
+      total_disk_readk  += ORCA_io_dev_info[i].kreads;
+      total_disk_writek += ORCA_io_dev_info[i].kwrites;
+      mean_disk_busy    += ORCA_io_dev_info[i].run_percent;
+      if (ORCA_io_dev_info[i].run_percent > peak_disk_busy) {
+         peak_disk_busy = ORCA_io_dev_info[i].run_percent;
       }
 #ifdef HAVE_EMC_DISK_CONTROL
     }

Added: trunk/orca/lib/SE/3.3.1/tapeinfo.se
==============================================================================
--- (empty file)
+++ trunk/orca/lib/SE/3.3.1/tapeinfo.se	Tue Sep 14 11:27:02 2004
@@ -0,0 +1,277 @@
+//
+// Copyright (c) 1993-2001 by Richard Pettit. All rights reserved.
+//
+// Some of this work was derived from include files containing the following
+// copyrights.
+//
+//   Copyright (c) 1986-1994 by Sun Microsystems, Inc.
+//   Copyright (c) 1983-1989 by AT&T
+//   Copyright (c) 1980-1993 by The Regents of the University of California.
+//
+// The work as a whole represents unique intellectual property and is
+// copyright by Richard Pettit as shown on the first line.
+//
+
+#ifndef _TAPEINFO_SE_
+#define _TAPEINFO_SE_
+
+#include <stdio.se>
+#include <string.se>
+#include <ctype.se>
+#include <stdlib.se>
+#include <unistd.se>
+#include <kstat.se>
+#include <sysdepend.se>
+#include <dirent.se>
+#include <se_trees.se>
+
+#define PATH_TO_INST     "/etc/path_to_inst"
+
+// sterr is not defined in kstat.se, so define here
+kstat struct "sterr:" ks_sterr {
+    int    number$;              // linear counter
+    string name$;                // name of error
+    int    instance$;            // instance number
+
+    uint64_t "Soft Errors";
+    uint64_t "Hard Errors";
+    uint64_t "Transport Errors";
+    string    Vendor;
+    string    Product;
+    string    Revision;
+    string   "Serial No";
+};
+
+struct tape_info_t {
+  string   short_name;
+  string   long_name;
+  ks_sterr errors;
+};
+
+// this is a global array to keep similarity with diskinfo.se
+// use functions provided below as access methods
+
+tape_info_t GLOBAL_tape_info[];
+int         GLOBAL_tapeinfo_size = 1;
+ulong_t     GLOBAL_tapeinfo_short_tree;
+ulong_t     GLOBAL_tapeinfo_long_tree;
+
+int	    tapeinfo_inst_initialized;	// set when data exists
+
+ks_sterr
+find_tape_error(string name)
+{
+  ks_sterr    sterr;
+  string      short_name;
+
+  if (name =~ "^st.*") {
+    sterr.number$ = 0;
+    for(refresh$(sterr); sterr.number$ != -1; sterr.number$++,refresh$(sterr)) {
+      short_name = sterr.name$;
+      strtok(short_name, ",");
+      if (short_name == name) {
+        break;
+      }
+    }
+    return sterr;
+  }
+}
+
+int
+setup_tapeinfo_inst()   // return 1 if OK, 0 if not
+{
+  char buf[BUFSIZ];
+  char points_at[MAXNAMELEN];
+  string p;
+  string full;
+  string path;
+  string tape_dirs[2] = { "/dev/rmt", nil };
+  int count = 0;
+  int i;
+  int n;
+  ulong ld;
+  ulong dirp;
+  ulong input;
+  dirent_t dp;
+  ulong_t path_tree;
+  ulong_t np;
+
+  if (tapeinfo_inst_initialized == 1) {
+    return 1;
+  }
+
+  path_tree = str2int_init();
+  if (path_tree == 0) {
+    return 0;
+  }
+
+  // load up the tree with the paths and quit traversing path_to_inst
+  input = fopen(PATH_TO_INST, "r");
+  if (input == 0) {
+    avlfree(path_tree);
+    return 0;
+  }
+  while (fgets(buf, sizeof(buf), input) != nil) {
+    if ((buf[0] != '#') && (buf[0] != '\n')) {
+      p = strtok(buf, " ");
+      n = atoi(strtok(nil, " "));
+      path = strtok(p, "\"");
+
+      if (str2int_put(path_tree, path, n) == -1) {
+        fclose(input);
+        avlfree(path_tree);
+        return 0;
+      }
+    }
+  }
+  fclose(input);
+
+  // create the global tape info array
+  GLOBAL_tape_info = new tape_info_t[GLOBAL_tapeinfo_size];
+
+  // scan /dev/rmt and insert tape entries
+  for (i=0; tape_dirs[i] != nil; i++) {
+    dirp = opendir(tape_dirs[i]);
+    if (dirp == 0) {
+      if (i > 0) {
+        // first is /dev/rmt
+        break;
+      }
+      avlfree(path_tree);
+      return 0;
+    }
+
+    for (ld = readdir(dirp); ld != 0; ld = readdir(dirp)) {
+      // grow the array if needed
+      if (count == GLOBAL_tapeinfo_size) {
+        GLOBAL_tapeinfo_size += 1;
+        GLOBAL_tape_info = renew GLOBAL_tape_info[GLOBAL_tapeinfo_size];
+      }
+      dp = *((dirent_t *) ld);
+
+      // skip . and ..
+      if (dp.d_name == "." || dp.d_name == "..") {
+        continue;
+      }
+
+      // skip everything but raw devices
+      if ( isdigit(dp.d_name[strlen(dp.d_name)-1]) == 0 ) {
+        continue;
+      }
+
+      // read the link
+      full = sprintf("%s/%s", tape_dirs[i], dp.d_name);
+
+      n = readlink(full, points_at, sizeof(points_at));
+      if (n == -1) {
+        closedir(dirp);
+        avlfree(path_tree);
+        return 0;
+      }
+      points_at[n] = '\0';
+
+      // chop off the :a at the end
+      strcpy(strrchr(points_at, ':'), "");
+
+      // hack off ../../devices from the start
+      sscanf(points_at, "../../devices%s", &points_at);
+
+      // hack off /dev/ from the start
+      // long name is the rmt/<tape device number>
+      sscanf(full, "/dev/%s", &buf);
+      GLOBAL_tape_info[count].long_name = buf;
+
+      GLOBAL_tape_info[count].short_name = nil;
+
+      // construct the short name
+      if ((np = str2int_get(path_tree, points_at)) != 0) {
+        n = ((int) *((ulong_t *) np));
+        p = strrchr(points_at, '/');
+        p = strtok(p, "/");
+        p = strtok(p, "@");
+        GLOBAL_tape_info[count].short_name = sprintf("%s%d", p, n);
+      }
+
+      // hard luck, can't find this device
+      if (GLOBAL_tape_info[count].short_name == nil) {
+        continue;
+      }
+
+      // squirrel this away while we're at it
+      GLOBAL_tape_info[count].errors =
+        find_tape_error(GLOBAL_tape_info[count].short_name);
+
+      count++;
+    }
+    closedir(dirp);
+  }
+
+  // tree the names for fast lookup
+  GLOBAL_tapeinfo_short_tree = str2int_init();
+  GLOBAL_tapeinfo_long_tree = str2int_init();
+  if ((GLOBAL_tapeinfo_short_tree == 0) || (GLOBAL_tapeinfo_long_tree == 0)) {
+    return 0;
+  }
+  for(i=0; i<count; i++) {
+    str2int_put(GLOBAL_tapeinfo_short_tree, GLOBAL_tape_info[i].short_name, i);
+    str2int_put(GLOBAL_tapeinfo_long_tree, GLOBAL_tape_info[i].long_name, i);
+  }
+
+  tapeinfo_inst_initialized = 1;
+  return 1;
+}
+
+// Function names must be changed to prevent conflict with diskinfo.se
+
+// use this function during init to map short names (st0) to indexes
+int
+find_tape_inst(string name)   // return index into GLOBAL_tape_info
+{
+  ulong_t lp;
+
+  if (setup_tapeinfo_inst() == 0) {
+    return -1;
+  }
+  lp = str2int_get(GLOBAL_tapeinfo_short_tree, name);
+  if (lp == 0) {
+    return -1;
+  }
+  return ((int) *((ulong_t *) lp));
+}
+#define find_tape_short_name find_tape_inst
+
+// use this function to do the reverse mapping from rmt/0
+int
+find_tape_long_name(string name)   // return index into GLOBAL_tape_info
+{
+  ulong_t lp;
+
+  if (setup_tapeinfo_inst() == 0) {
+    return -1;
+  }
+  lp = str2int_get(GLOBAL_tapeinfo_long_tree, name);
+  if (lp == 0) {
+    return -1;
+  }
+  return ((int) *((ulong_t *) lp));
+}
+
+// use this function to get the data for an index
+tape_info_t
+tape_info(int i, string name) 
+{
+  tape_info_t no_info;
+
+  if (setup_tapeinfo_inst() == 0) {
+    return no_info;
+  }
+  if (i >= 0 && i < GLOBAL_tapeinfo_size) {
+    return GLOBAL_tape_info[i];
+  } else {
+    no_info.short_name = name;
+    no_info.long_name = name;
+    return no_info;
+  }
+}
+
+#endif



More information about the Orca-checkins mailing list