1 /* Copyright (c) 2017 Daniel Widdis, All Rights Reserved
2  *
3  * The contents of this file is dual-licensed under 2
4  * alternative Open Source/Free licenses: LGPL 2.1 or later and
5  * Apache License 2.0. (starting with JNA version 4.0.0).
6  *
7  * You can freely decide which license you want to apply to
8  * the project.
9  *
10  * You may obtain a copy of the LGPL License at:
11  *
12  * http://www.gnu.org/licenses/licenses.html
13  *
14  * A copy is also included in the downloadable source code package
15  * containing JNA, in file "LGPL2.1".
16  *
17  * You may obtain a copy of the Apache License at:
18  *
19  * http://www.apache.org/licenses/
20  *
21  * A copy is also included in the downloadable source code package
22  * containing JNA, in file "AL2.0".
23  */
24 package com.sun.jna.platform.unix.solaris;
25 
26 import java.util.Arrays;
27 import java.util.List;
28 
29 import com.sun.jna.Library;
30 import com.sun.jna.Native;
31 import com.sun.jna.Pointer;
32 import com.sun.jna.Structure;
33 import com.sun.jna.Structure.FieldOrder;
34 import com.sun.jna.Union;
35 
36 /**
37  * Kstat library. The kstat facility is a general-purpose mechanism for
38  * providing kernel statistics to users.
39  *
40  * @author widdis[at]gmail[dot]com
41  */
42 public interface LibKstat extends Library {
43 
44     LibKstat INSTANCE = Native.load("kstat", LibKstat.class);
45 
46     /*
47      * Kstat Data Types
48      */
49     // The "raw" kstat type is just treated as an array of bytes. This is
50     // generally used to export well-known structures, like sysinfo.
51     byte KSTAT_TYPE_RAW = 0;
52 
53     byte KSTAT_TYPE_NAMED = 1; // name/value pairs
54 
55     byte KSTAT_TYPE_INTR = 2; // interrupt statistics
56 
57     byte KSTAT_TYPE_IO = 3; // I/O statistics
58 
59     byte KSTAT_TYPE_TIMER = 4; // event timers
60 
61     /*
62      * KstatNamed Data Types (for selecting from Union)
63      */
64     byte KSTAT_DATA_CHAR = 0;
65 
66     byte KSTAT_DATA_INT32 = 1;
67 
68     byte KSTAT_DATA_UINT32 = 2;
69 
70     byte KSTAT_DATA_INT64 = 3;
71 
72     byte KSTAT_DATA_UINT64 = 4;
73 
74     byte KSTAT_DATA_STRING = 9;
75 
76     /*
77      * KstatIntr Interrupts
78      */
79     int KSTAT_INTR_HARD = 0;
80 
81     int KSTAT_INTR_SOFT = 1;
82 
83     int KSTAT_INTR_WATCHDOG = 2;
84 
85     int KSTAT_INTR_SPURIOUS = 3;
86 
87     int KSTAT_INTR_MULTSVC = 4;
88 
89     int KSTAT_NUM_INTRS = 5;
90 
91     int KSTAT_STRLEN = 31; // 30 chars + NULL; must be 16 * n - 1
92 
93     int EAGAIN = 11; // Temporarily busy
94 
95     /**
96      * The kernel maintains a linked list of statistics structures, or kstats.
97      * Each kstat has a common header section and a type-specific data section.
98      * The header section is defined by the kstat_t structure
99      */
100     @FieldOrder({"ks_crtime", "ks_next", "ks_kid", "ks_module", "ks_resv", "ks_instance",
101         "ks_name", "ks_type", "ks_class", "ks_flags", "ks_data", "ks_ndata", "ks_data_size", "ks_snaptime",
102         "ks_update", "ks_private", "ks_snapshot", "ks_lock"})
103     class Kstat extends Structure {
104 
105         // Fields relevant to both kernel and user
106         public long ks_crtime; // creation time
107 
108         public Pointer ks_next; // kstat chain linkage
109 
110         public int ks_kid; // unique kstat ID
111 
112         public byte[] ks_module = new byte[KSTAT_STRLEN]; // module name
113 
114         public byte ks_resv; // reserved
115 
116         public int ks_instance; // module's instance
117 
118         public byte[] ks_name = new byte[KSTAT_STRLEN]; // kstat name
119 
120         public byte ks_type; // kstat data type
121 
122         public byte[] ks_class = new byte[KSTAT_STRLEN]; // kstat class
123 
124         public byte ks_flags; // kstat flags
125 
126         public Pointer ks_data; // kstat type-specific data
127 
128         public int ks_ndata; // # of data records
129 
130         public long ks_data_size; // size of kstat data section
131 
132         public long ks_snaptime; // time of last data snapshot
133 
134         // Fields relevant to kernel only
135         public int ks_update; // dynamic update function
136 
137         public Pointer ks_private; // provider-private data
138 
139         public int ks_snapshot; // snapshot function
140 
141         public Pointer ks_lock; // protects this kstat's data
142 
next()143         public Kstat next() {
144             if (ks_next == null) {
145                 return null;
146             }
147             Kstat n = new Kstat();
148             n.useMemory(ks_next);
149             n.read();
150             return n;
151         }
152     }
153 
154     /**
155      * A list of arbitrary name=value statistics.
156      */
157     @FieldOrder({"name", "data_type", "value"})
158     class KstatNamed extends Structure {
159 
160         public byte[] name = new byte[KSTAT_STRLEN]; // name of counter
161 
162         public byte data_type; // data type
163 
164         public UNION value; // value of counter
165 
166         public static class UNION extends Union {
167 
168             public byte[] charc = new byte[16]; // enough for 128-bit ints
169 
170             public int i32;
171 
172             public int ui32;
173 
174             public long i64;
175 
176             public long ui64;
177 
178             public STR str;
179 
180             @FieldOrder({"addr", "len"})
181             public static class STR extends Structure {
182 
183                 public Pointer addr;
184 
185                 public int len; // length of string
186 
187             }
188         }
189 
KstatNamed()190         public KstatNamed() {
191             super();
192         }
193 
KstatNamed(Pointer p)194         public KstatNamed(Pointer p) {
195             super(p);
196             read();
197         }
198 
199         @Override
read()200         public void read() {
201             super.read();
202             switch (data_type) {
203                 case KSTAT_DATA_CHAR:
204                     value.setType(byte[].class);
205                     break;
206                 case KSTAT_DATA_STRING:
207                     value.setType(UNION.STR.class);
208                     break;
209                 case KSTAT_DATA_INT32:
210                 case KSTAT_DATA_UINT32:
211                     value.setType(int.class);
212                     break;
213                 case KSTAT_DATA_INT64:
214                 case KSTAT_DATA_UINT64:
215                     value.setType(long.class);
216                     break;
217                 default:
218                     break;
219             }
220             value.read();
221         }
222     }
223 
224     /**
225      * Interrupt statistics. An interrupt is a hard interrupt (sourced from the
226      * hardware device itself), a soft interrupt (induced by the system via the
227      * use of some system interrupt source), a watchdog interrupt (induced by a
228      * periodic timer call), spurious (an interrupt entry point was entered but
229      * there was no interrupt to service), or multiple service (an interrupt was
230      * detected and serviced just prior to returning from any of the other
231      * types).
232      */
233     @FieldOrder({"intrs"})
234     class KstatIntr extends Structure {
235 
236         public int[] intrs = new int[KSTAT_NUM_INTRS]; // interrupt counters
237 
238     }
239 
240     /**
241      * Event timer statistics. These provide basic counting and timing
242      * information for any type of event.
243      */
244     @FieldOrder({"name", "resv", "num_events", "elapsed_time", "min_time", "max_time",
245         "start_time", "stop_time"})
246     class KstatTimer extends Structure {
247 
248         public byte[] name = new byte[KSTAT_STRLEN]; // event name
249 
250         public byte resv; // reserved
251 
252         public long num_events; // number of events
253 
254         public long elapsed_time; // cumulative elapsed time
255 
256         public long min_time; // shortest event duration
257 
258         public long max_time; // longest event duration
259 
260         public long start_time; // previous event start time
261 
262         public long stop_time; // previous event stop time
263 
264     }
265 
266     /**
267      * IO Statistics.
268      */
269     @FieldOrder({"nread", "nwritten", "reads", "writes", "wtime", "wlentime",
270         "wlastupdate", "rtime", "rlentime", "rlastupdate", "wcnt", "rcnt"})
271     class KstatIO extends Structure {
272 
273         // Basic counters.
274         public long nread; // number of bytes read
275 
276         public long nwritten; // number of bytes written
277 
278         public int reads; // number of read operations
279 
280         public int writes; // number of write operations
281         /*-
282         * Accumulated time and queue length statistics.
283         *
284         * Time statistics are kept as a running sum of "active" time.
285         * Queue length statistics are kept as a running sum of the
286         * product of queue length and elapsed time at that length --
287         * that is, a Riemann sum for queue length integrated against time.
288         *       ^
289         *       |           _________
290         *       8           | i4    |
291         *       |           |   |
292         *   Queue   6           |   |
293         *   Length  |   _________   |   |
294         *       4   | i2    |_______|   |
295         *       |   |   i3      |
296         *       2_______|           |
297         *       |    i1             |
298         *       |_______________________________|
299         *       Time--  t1  t2  t3  t4
300         *
301         * At each change of state (entry or exit from the queue),
302         * we add the elapsed time (since the previous state change)
303         * to the active time if the queue length was non-zero during
304         * that interval; and we add the product of the elapsed time
305         * times the queue length to the running length*time sum.
306         *
307         * This method is generalizable to measuring residency
308         * in any defined system: instead of queue lengths, think
309         * of "outstanding RPC calls to server X".
310         *
311         * A large number of I/O subsystems have at least two basic
312         * "lists" of transactions they manage: one for transactions
313         * that have been accepted for processing but for which processing
314         * has yet to begin, and one for transactions which are actively
315         * being processed (but not done). For this reason, two cumulative
316         * time statistics are defined here: pre-service (wait) time,
317         * and service (run) time.
318         *
319         * The units of cumulative busy time are accumulated nanoseconds.
320         * The units of cumulative length*time products are elapsed time
321         * times queue length.
322         */
323 
324         public long wtime; // cumulative wait (pre-service) time
325 
326         public long wlentime; // cumulative wait length*time product
327 
328         public long wlastupdate; // last time wait queue changed
329 
330         public long rtime; // cumulative run (service) time
331 
332         public long rlentime; // cumulative run length*time product
333 
334         public long rlastupdate; // last time run queue changed
335 
336         public int wcnt; // count of elements in wait state
337 
338         public int rcnt; // count of elements in run state
339 
KstatIO()340         public KstatIO() {
341             super();
342         }
343 
KstatIO(Pointer p)344         public KstatIO(Pointer p) {
345             super(p);
346             read();
347         }
348     }
349 
350     /**
351      * A kstat control structure. Only one thread may actively use a KstatCtl
352      * value at any time. Synchronization is left to the application.
353      */
354     @FieldOrder({"kc_chain_id", "kc_chain", "kc_kd"})
355     class KstatCtl extends Structure {
356 
357         public int kc_chain_id; // current kstat chain ID
358 
359         public Kstat kc_chain; // pointer to kstat chain
360 
361         public int kc_kd; // /dev/kstat descriptor - not public interface
362 
363     }
364 
365     /**
366      * The kstat_open() function initializes a kstat control structure, which
367      * provides access to the kernel statistics library.
368      *
369      * @return A pointer to this structure, which must be supplied as the kc
370      *         argument in subsequent libkstat function calls.
371      */
kstat_open()372     KstatCtl kstat_open();
373 
374     /**
375      * The kstat_close() function frees all resources that were associated with
376      * kc.
377      *
378      * @param kc
379      *            a kstat control structure
380      * @return 0 on success and -1 on failure.
381      */
kstat_close(KstatCtl kc)382     int kstat_close(KstatCtl kc);
383 
384     /**
385      * The kstat_chain_update() function brings the user's kstat header chain in
386      * sync with that of the kernel. The kstat chain is a linked list of kstat
387      * headers (kstat_t's) pointed to by kc.kc_chain, which is initialized by
388      * kstat_open(3KSTAT). This chain constitutes a list of all kstats currently
389      * in the system. During normal operation, the kernel creates new kstats and
390      * delete old ones as various device instances are added and removed,
391      * thereby causing the user's copy of the kstat chain to become out of date.
392      * The kstat_chain_update() function detects this condition by comparing the
393      * kernel's current kstat chain ID(KCID), which is incremented every time
394      * the kstat chain changes, to the user's KCID, kc.kc_chain_id. If the KCIDs
395      * match, kstat_chain_update() does nothing. Otherwise, it deletes any
396      * invalid kstat headers from the user's kstat chain, adds any new ones, and
397      * sets kc.kc_chain_id to the new KCID. All other kstat headers in the
398      * user's kstat chain are unmodified.
399      *
400      * @param kc
401      *            a kstat control structure
402      * @return the new KCID if the kstat chain has changed, 0 if it hasn't, or
403      *         -1 on failure.
404      */
kstat_chain_update(KstatCtl kc)405     int kstat_chain_update(KstatCtl kc);
406 
407     /**
408      * kstat_read() gets data from the kernel for the kstat pointed to by ksp.
409      * ksp.ks_data is automatically allocated (or reallocated) to be large
410      * enough to hold all of the data. ksp.ks_ndata is set to the number of data
411      * fields, ksp.ks_data_size is set to the total size of the data, and
412      * ksp.ks_snaptime is set to the high-resolution time at which the data
413      * snapshot was taken.
414      *
415      * @param kc
416      *            The kstat control structure
417      * @param ksp
418      *            The kstat from which to retrieve data
419      * @param p
420      *            If buf is non-NULL , the data is copied from ksp.ks_data into
421      *            buf.
422      * @return On success, return the current kstat chain ID (KCID). On failure,
423      *         return -1.
424      */
kstat_read(KstatCtl kc, Kstat ksp, Pointer p)425     int kstat_read(KstatCtl kc, Kstat ksp, Pointer p);
426 
427     /**
428      * kstat_write() writes data from buf, or from ksp.ks_data if buf is NULL,
429      * to the corresponding kstat in the kernel. Only the superuser can use
430      * kstat_write() .
431      *
432      * @param kc
433      *            The kstat control structure
434      * @param ksp
435      *            The kstat on which to set data
436      * @param buf
437      *            If buf is non-NULL, the data is copied from buf into
438      *            ksp.ks_data.
439      * @return On success, return the current kstat chain ID (KCID). On failure,
440      *         return -1.
441      */
kstat_write(KstatCtl kc, Kstat ksp, Pointer buf)442     int kstat_write(KstatCtl kc, Kstat ksp, Pointer buf);
443 
444     /**
445      * The kstat_lookup() function traverses the kstat chain, kc.kc_chain,
446      * searching for a kstat with the same ks_module, ks_instance, and ks_name
447      * fields; this triplet uniquely identifies a kstat. If ks_module is NULL,
448      * ks_instance is -1, or ks_name is NULL, then those fields will be ignored
449      * in the search. For example, kstat_lookup(kc, NULL, -1, "foo") will simply
450      * find the first kstat with name "foo".
451      *
452      * @param kc
453      *            The kstat control structure
454      * @param ks_module
455      *            The kstat module to search
456      * @param ks_instance
457      *            The kstat instance number
458      * @param ks_name
459      *            The kstat name to search
460      * @return a pointer to the requested kstat if it is found, or NULL if it is
461      *         not.
462      */
kstat_lookup(KstatCtl kc, String ks_module, int ks_instance, String ks_name)463     Kstat kstat_lookup(KstatCtl kc, String ks_module, int ks_instance, String ks_name);
464 
465     /**
466      * The kstat_data_lookup() function searches the kstat's data section for
467      * the record with the specified name . This operation is valid only for
468      * kstat types which have named data records. Currently, only the
469      * KSTAT_TYPE_NAMED and KSTAT_TYPE_TIMER kstats have named data records.
470      *
471      * @param ksp
472      *            The kstat to search
473      * @param name
474      *            The key for the name-value pair, or name of the timer as
475      *            applicable
476      * @return a pointer to the requested data record if it is found. If the
477      *         requested record is not found, or if the kstat type is invalid,
478      *         returns NULL.
479      */
kstat_data_lookup(Kstat ksp, String name)480     Pointer kstat_data_lookup(Kstat ksp, String name);
481 }
482