ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/i-scream/projects/libstatgrab/src/libstatgrab/win32.c
Revision: 1.2
Committed: Sat Feb 18 15:24:59 2006 UTC (18 years, 2 months ago) by tdb
Content type: text/plain
Branch: MAIN
CVS Tags: LIBSTATGRAB_0_17, LIBSTATGRAB_0_16, LIBSTATGRAB_0_15, LIBSTATGRAB_0_14, LIBSTATGRAB_0_13, HEAD
Changes since 1.1: +6 -6 lines
Log Message:
Apply fix to Win32 code.

Patch by:	"Tim Teulings" <rael@edge.ping.de>

File Contents

# User Rev Content
1 tdb 1.1 #include "statgrab.h"
2     #ifdef WIN32
3     #include <pdh.h>
4     #include <pdhmsg.h>
5     #include "win32.h"
6     #include <stdio.h>
7     #include "tools.h"
8    
9     static HQUERY h_query;
10    
11     static HCOUNTER current_han[SG_WIN32_SIZE];
12    
13     static char **diskio_names;
14     static HCOUNTER *diskio_rhan;
15     static HCOUNTER *diskio_whan;
16     static int diskio_no;
17    
18     static int is_started = 0;
19    
20     /*static char **netio_names;
21     static HCOUNTER *netio_rhan;
22     static HCOUNTER *netio_shan;
23     static int netio_no;*/
24    
25     int add_counter(const char *fullCounterPath, HCOUNTER *phCounter)
26     {
27     PDH_STATUS pdh_status;
28    
29     pdh_status = PdhAddCounter(h_query, fullCounterPath,
30     0, phCounter);
31     if(pdh_status != ERROR_SUCCESS) {
32     //sg_set_error(SG_ERROR_PDHADD, fullCounterPath);
33     phCounter = NULL;
34     return -1;
35     }
36     return 0;
37     }
38    
39     int read_counter_double(pdh_enum counter, double *result)
40     {
41     PDH_STATUS pdh_status;
42     PDH_FMT_COUNTERVALUE *item_buf;
43 tdb 1.2 HCOUNTER hcounter = current_han[counter];
44 tdb 1.1
45 tdb 1.2 if(hcounter == NULL)
46 tdb 1.1 return -1;
47    
48     item_buf = sg_malloc(sizeof(PDH_FMT_COUNTERVALUE));
49     if (item_buf == NULL) {
50     return -1;
51     }
52    
53 tdb 1.2 pdh_status = PdhGetFormattedCounterValue(hcounter, PDH_FMT_DOUBLE, NULL,
54 tdb 1.1 item_buf);
55     if(pdh_status != ERROR_SUCCESS) {
56     free(item_buf);
57     return -1;
58     }
59     *result = item_buf->doubleValue;
60     free(item_buf);
61     return 0;
62     }
63    
64 tdb 1.2 static int read_counter_large_int(HCOUNTER hcounter, long long *result)
65 tdb 1.1 {
66     PDH_STATUS pdh_status;
67     PDH_FMT_COUNTERVALUE *item_buf;
68    
69 tdb 1.2 if(hcounter == NULL)
70 tdb 1.1 return -1;
71    
72     item_buf = sg_malloc(sizeof(PDH_FMT_COUNTERVALUE));
73     if (item_buf == NULL) {
74     return -1;
75     }
76    
77 tdb 1.2 pdh_status = PdhGetFormattedCounterValue(hcounter, PDH_FMT_LARGE, NULL,
78 tdb 1.1 item_buf);
79     if(pdh_status != ERROR_SUCCESS) {
80     free(item_buf);
81     /*switch(pdh_status) {
82     case PDH_INVALID_ARGUMENT:
83     printf("invalid argument\n");
84     break;
85     case PDH_INVALID_DATA:
86     printf("invalid data\n");
87     break;
88     case PDH_INVALID_HANDLE:
89     printf("invalid handle\n");
90     break;
91     }*/
92     return -1;
93     }
94     *result = item_buf->largeValue;
95     free(item_buf);
96     return 0;
97     }
98    
99     int read_counter_large(pdh_enum counter, long long *result)
100     {
101     return read_counter_large_int(current_han[counter], result);
102     }
103    
104     static char *get_instances(const char *object)
105     {
106     PDH_STATUS pdh_status;
107     char *instancelistbuf;
108     DWORD instancelistsize = 0;
109     char *counterlistbuf;
110     DWORD counterlistsize = 0;
111    
112     /* Get necessary size of buffers */
113     pdh_status = PdhEnumObjectItems(NULL, NULL, object, NULL,
114     &counterlistsize, NULL, &instancelistsize,
115     PERF_DETAIL_WIZARD, 0);
116     /* 2k is dodgy and returns ERROR_SUCCESS even though the buffers were
117     * NULL */
118     if(pdh_status == PDH_MORE_DATA || pdh_status == ERROR_SUCCESS) {
119     instancelistbuf = sg_malloc(instancelistsize * sizeof(TCHAR));
120     counterlistbuf = sg_malloc(counterlistsize * sizeof(TCHAR));
121     if (instancelistbuf != NULL && counterlistbuf != NULL) {
122     pdh_status = PdhEnumObjectItems(NULL, NULL, object,
123     counterlistbuf, &counterlistsize,
124     instancelistbuf, &instancelistsize,
125     PERF_DETAIL_WIZARD, 0);
126     if (pdh_status == ERROR_SUCCESS) {
127     free(counterlistbuf);
128     return instancelistbuf;
129     }
130     }
131     if (counterlistbuf != NULL)
132     free(counterlistbuf);
133     if(instancelistbuf != NULL)
134     free(instancelistbuf);
135     }
136     return NULL;
137     }
138    
139     /* Gets the instance buffer. Removes _Total item. Works out how many items
140     * there are. Returns these in a pointer list, rather than single buffer.
141     */
142     static char **get_instance_list(const char *object, int *n)
143     {
144     char *thisinstance = NULL;
145     char *instances = NULL;
146     char **list;
147     char **listtmp = NULL;
148     int i;
149     *n = 0;
150    
151     instances = get_instances(object);
152     if (instances == NULL)
153     return NULL;
154    
155     list = (char **)sg_malloc(sizeof(char *));
156     if (list == NULL) {
157     return NULL;
158     }
159     for (thisinstance = instances; *thisinstance != 0;
160     thisinstance += strlen(thisinstance) + 1) {
161     /* Skip over the _Total item */
162     if (strcmp(thisinstance,"_Total") == 0) continue;
163    
164     listtmp = (char **)sg_realloc(list, sizeof(char *) * ((*n)+1));
165     if (listtmp == NULL) {
166     goto out;
167     }
168     list = listtmp;
169     list[*n] = sg_malloc(strlen(thisinstance) +1);
170     if(list[*n] == NULL) {
171     goto out;
172     }
173     list[*n] = strcpy(list[*n], thisinstance);
174     ++*n;
175     }
176     free (instances);
177     return list;
178    
179     out:
180     for (i = 0; i < *n; i++) {
181     free(list[i]);
182     }
183     free(list);
184     return NULL;
185     }
186    
187     char *get_diskio(const int no, long long *read, long long *write)
188     {
189     int result;
190     char *name = NULL;
191    
192     if (no >= diskio_no || no < 0)
193     return NULL;
194    
195     result = read_counter_large_int(diskio_rhan[no], read);
196     result = result + read_counter_large_int(diskio_whan[no], write);
197     if (result) {
198     sg_set_error(SG_ERROR_PDHREAD, "diskio");
199     return NULL;
200     }
201     if (sg_update_string(&name, diskio_names[no]))
202     return NULL;
203     return name;
204     }
205    
206     /* We do not fail on add_counter here, as some counters may not exist on all
207     * hosts. The rest will work, and the missing/failed counters will die nicely
208     * elsewhere */
209     static int add_all_monitors()
210     {
211     int i;
212     char tmp[512];
213    
214     add_counter(PDH_USER, &(current_han[SG_WIN32_PROC_USER]));
215     add_counter(PDH_PRIV, &(current_han[SG_WIN32_PROC_PRIV]));
216     add_counter(PDH_IDLE, &(current_han[SG_WIN32_PROC_IDLE]));
217     add_counter(PDH_INTER, &(current_han[SG_WIN32_PROC_INT]));
218     add_counter(PDH_MEM_CACHE, &(current_han[SG_WIN32_MEM_CACHE]));
219     add_counter(PDH_UPTIME, &(current_han[SG_WIN32_UPTIME]));
220     add_counter(PDH_PAGEIN, &(current_han[SG_WIN32_PAGEIN]));
221     add_counter(PDH_PAGEOUT, &(current_han[SG_WIN32_PAGEOUT]));
222    
223     diskio_names = get_instance_list("PhysicalDisk", &diskio_no);
224     if (diskio_names != NULL) {
225     diskio_rhan = (HCOUNTER *)malloc(sizeof(HCOUNTER) * diskio_no);
226     if (diskio_rhan == NULL) {
227     PdhCloseQuery(h_query);
228     return -1;
229     }
230     diskio_whan = (HCOUNTER *)malloc(sizeof(HCOUNTER) * diskio_no);
231     if (diskio_whan == NULL) {
232     PdhCloseQuery(h_query);
233     free (diskio_rhan);
234     return -1;
235     }
236     for (i = 0; i < diskio_no; i++) {
237     snprintf(tmp, sizeof(tmp), PDH_DISKIOREAD, diskio_names[i]);
238     add_counter(tmp, &diskio_rhan[i]);
239    
240     snprintf(tmp, sizeof(tmp), PDH_DISKIOWRITE, diskio_names[i]);
241     add_counter(tmp, &diskio_whan[i]);
242     }
243     }
244     return 0;
245     }
246     #endif
247    
248     /* Call before trying to get search results back, otherwise it'll be dead data
249     */
250     int sg_win32_snapshot()
251     {
252     #ifdef WIN32
253     PDH_STATUS pdh_status;
254    
255     if(!is_started) {
256     return -1;
257     }
258    
259     pdh_status = PdhCollectQueryData(h_query);
260     if(pdh_status != ERROR_SUCCESS) {
261     sg_set_error(SG_ERROR_PDHCOLLECT, NULL);
262     return -1;
263     }
264     #endif
265     return 0;
266     }
267    
268     /* Must be called before any values can be read. This creates all the
269     * necessary PDH values
270     */
271     int sg_win32_start_capture()
272     {
273     #ifdef WIN32
274     PDH_STATUS pdh_status;
275    
276     if(is_started) {
277     return -1;
278     }
279    
280     pdh_status = PdhOpenQuery(NULL, 0, &h_query);
281    
282     if(pdh_status != ERROR_SUCCESS) {
283     char *mess = NULL;
284     if(pdh_status == PDH_INVALID_ARGUMENT)
285     mess = "Invalid argument o.O";
286     else if(pdh_status == PDH_MEMORY_ALLOCATION_FAILURE)
287     mess = "Memory allocation failure";
288     sg_set_error(SG_ERROR_PDHOPEN, mess);
289     return -1;
290     }
291     if (add_all_monitors() == -1) {
292     return -1;
293     }
294    
295     is_started = 1;
296     #endif
297     return 0;
298     }
299    
300     /* Must be called before the program exits, or to close all the capture items
301     * before opening with a call to start_capture
302     */
303     void sg_win32_end_capture()
304     {
305     #ifdef WIN32
306     int i;
307     PDH_STATUS pdh_status;
308    
309     if(!is_started) {
310     return;
311     }
312    
313     pdh_status = PdhCloseQuery(h_query);
314     for (i=0; i < SG_WIN32_SIZE; ++i) {
315     PdhRemoveCounter(current_han[i]);
316     current_han[i] = NULL;
317     }
318     /*free_io(&diskio_no, diskio_names, diskio_rhan, diskio_whan);
319     free_io(&netio_no, netio_names, netio_rhan, netio_shan);*/
320     for (i=0; i < diskio_no; ++i) {
321     PdhRemoveCounter(diskio_rhan[i]);
322     PdhRemoveCounter(diskio_whan[i]);
323     free(diskio_names[i]);
324     }
325     free(diskio_names);
326     free(diskio_rhan);
327     free(diskio_whan);
328     diskio_no = 0;
329    
330     is_started = 0;
331     #endif
332     }
333