Annotation of parser3/src/types/pa_vstatus.C, revision 1.51
1.1 paf 1: /** @file
2: Parser: @b status class impl.
3:
1.49 moko 4: Copyright (c) 2001-2026 Art. Lebedev Studio (https://www.artlebedev.com)
1.42 moko 5: Authors: Konstantin Morshnev <moko@design.ru>, Alexandr Petrosian <paf@design.ru>
1.16 paf 6:
7: Win32 rusage author: Victor Fedoseev <vvf_ru@mail.ru>
1.8 paf 8: */
1.1 paf 9:
10: #include "pa_vstatus.h"
11: #include "pa_cache_managers.h"
1.2 paf 12: #include "pa_vhash.h"
13: #include "pa_vdouble.h"
1.44 moko 14: #include "pa_vstring.h"
1.23 paf 15: #include "pa_threads.h"
1.51 ! moko 16: #include "pa_http.h"
1.2 paf 17:
1.51 ! moko 18: volatile const char * IDENT_PA_VSTATUS_C="$Id: pa_vstatus.C,v 1.50 2026/10/12 21:59:21 moko Exp $" IDENT_PA_VSTATUS_H;
1.28 moko 19:
1.30 moko 20: #ifdef _MSC_VER
1.16 paf 21: #include <windows.h>
22: #include "psapi.h"
23:
24: // should be in windows.h, but were't
25: typedef struct _IO_COUNTERS_ {
26: ULONGLONG ReadOperationCount;
27: ULONGLONG WriteOperationCount;
28: ULONGLONG OtherOperationCount;
29: ULONGLONG ReadTransferCount;
30: ULONGLONG WriteTransferCount;
31: ULONGLONG OtherTransferCount;
32: } IO_COUNTERS_;
33: typedef IO_COUNTERS_ *PIO_COUNTERS_;
34:
35: typedef unsigned __int64 ui64;
36: // kernel32.dll (NT/2K/XP)
37: typedef BOOL (WINAPI *PGETPROCESSTIMES)(HANDLE,LPFILETIME,LPFILETIME,LPFILETIME,LPFILETIME);
38: //typedef BOOL (WINAPI *PGETPROCESSHEAPS)(DWORD,PHANDLE);
39: typedef BOOL (WINAPI *GETPROCESSIOCOUNTERS)(HANDLE,PIO_COUNTERS_);
40: // psapi.dll (2K/XP)
41: typedef BOOL (WINAPI *PGETPROCESSMEMORYINFO)(HANDLE,PPROCESS_MEMORY_COUNTERS,DWORD);
42:
43: // from CRT time.c
44: /*
45: * Number of 100 nanosecond units from 1/1/1601 to 1/1/1970
46: */
47: #define EPOCH_BIAS 116444736000000000i64
48:
49: /*
50: * Union to facilitate converting from FILETIME to unsigned __int64
51: */
52: typedef union {
1.40 moko 53: unsigned __int64 ft_scalar;
54: FILETIME ft_struct;
55: } FT;
56:
1.41 moko 57: int gettimeofday(struct timeval *tv, void *) {
1.40 moko 58: FT ft;
59: GetSystemTimeAsFileTime( &(ft.ft_struct) );
60: ft.ft_scalar -= EPOCH_BIAS;
1.41 moko 61: tv->tv_sec = (long)(ft.ft_scalar/10000000i64);
62: tv->tv_usec = (long)((ft.ft_scalar- tv->tv_sec*10000000i64)/10i64);
1.40 moko 63: return 0;
64: }
1.16 paf 65:
66: #endif
67:
1.17 paf 68: Value& rusage_element() {
69: VHash& rusage=*new VHash;
70: HashStringValue& hash=rusage.hash();
1.16 paf 71:
1.30 moko 72: #ifdef _MSC_VER
1.17 paf 73: double d1;
74: HANDLE hProc = GetCurrentProcess();
1.16 paf 75:
1.17 paf 76: HMODULE hMod = LoadLibrary("kernel32.dll");
77: if(hMod){
78: // NT/2K/XP
79: PGETPROCESSTIMES pGetProcessTimes = (PGETPROCESSTIMES)GetProcAddress(hMod, "GetProcessTimes");
80: if(pGetProcessTimes){
81: FILETIME CreationTime, ExitTime;
82: FT KernelTime, UserTime;
83: if(pGetProcessTimes(hProc, &CreationTime, &ExitTime, &KernelTime.ft_struct, &UserTime.ft_struct)){
84: // dwHighDateTime & dwLowDateTime - 1/10 000 000 seconds in 64 bit
85: /* the amount of time that the process has executed in user mode */
86: d1 = double((LONGLONG)UserTime.ft_scalar)/10000000.0;
1.46 moko 87: HASH_PUT_CSTR(hash, "utime", new VDouble(d1));
1.17 paf 88:
89: /* the amount of time that the process has executed in kernel mode */
90: d1 = double((LONGLONG)KernelTime.ft_scalar)/10000000.0;
1.46 moko 91: HASH_PUT_CSTR(hash, "stime", new VDouble(d1));
1.16 paf 92: }
1.17 paf 93: }
1.16 paf 94:
1.17 paf 95: // NT/2K/XP
96: GETPROCESSIOCOUNTERS pGetProcessIoCounters = (GETPROCESSIOCOUNTERS)GetProcAddress(hMod, "GetProcessIoCounters");
97: if(pGetProcessIoCounters){
98: IO_COUNTERS_ ioc;
99: if(pGetProcessIoCounters(hProc, &ioc)){
100: /* Specifies the number of I/O operations performed, other than read and write operations */
1.46 moko 101: HASH_PUT_CSTR(hash, "OtherOperationCount", new VDouble(double((LONGLONG)ioc.OtherOperationCount)));
1.17 paf 102: /* Specifies the number of bytes transferred during operations other than read and write operations */
1.46 moko 103: HASH_PUT_CSTR(hash, "OtherTransferCount", new VDouble(double((LONGLONG)ioc.OtherTransferCount)/1024.0));
1.17 paf 104: /* Specifies the number of read operations performed */
1.46 moko 105: HASH_PUT_CSTR(hash, "ReadOperationCount", new VDouble(double((LONGLONG)ioc.ReadOperationCount)));
1.17 paf 106: /* Specifies the number of bytes read */
1.46 moko 107: HASH_PUT_CSTR(hash, "ReadTransferCount", new VDouble(double((LONGLONG)ioc.ReadTransferCount)/1024.0));
1.17 paf 108: /* Specifies the number of write operations performed */
1.46 moko 109: HASH_PUT_CSTR(hash, "WriteOperationCount", new VDouble(double((LONGLONG)ioc.WriteOperationCount)));
1.17 paf 110: /* Specifies the number of bytes written */
1.46 moko 111: HASH_PUT_CSTR(hash, "WriteTransferCount", new VDouble(double((LONGLONG)ioc.WriteTransferCount)/1024.0));
1.16 paf 112: }
113: }
1.17 paf 114: FreeLibrary(hMod);
115: /*
116: PGETPROCESSHEAPS pGetProcessHeaps = (PGETPROCESSHEAPS)GetProcAddress(hMod, "GetProcessHeaps");
117: if(pGetProcessHeaps){
118: }
119: */
120: }
1.16 paf 121:
1.17 paf 122: // 2K/XP
123: hMod = LoadLibrary("psapi.dll");
124: if(hMod){
125: PGETPROCESSMEMORYINFO pGetProcessMemoryInfo = (PGETPROCESSMEMORYINFO)GetProcAddress(hMod, "GetProcessMemoryInfo");
126: if(pGetProcessMemoryInfo){
127: PROCESS_MEMORY_COUNTERS pmc;
128: pmc.cb = sizeof(PROCESS_MEMORY_COUNTERS);
129: if(pGetProcessMemoryInfo(hProc, &pmc, sizeof(PROCESS_MEMORY_COUNTERS))){
130: /* The peak working set size */
131: d1 = double(pmc.PeakWorkingSetSize)/1024.0;
1.46 moko 132: HASH_PUT_CSTR(hash, "maxrss", new VDouble(d1));
1.17 paf 133: /* The peak nonpaged pool usage */
134: d1 = double(pmc.QuotaPeakNonPagedPoolUsage)/1024.0;
1.46 moko 135: HASH_PUT_CSTR(hash, "QuotaPeakNonPagedPoolUsage", new VDouble(d1));
1.17 paf 136: /* The peak paged pool usage */
137: d1 = double(pmc.QuotaPeakPagedPoolUsage)/1024.0;
1.46 moko 138: HASH_PUT_CSTR(hash, "QuotaPeakPagedPoolUsage", new VDouble(d1));
1.17 paf 139: /* The peak pagefile usage */
140: d1 = double(pmc.PeakPagefileUsage)/1024.0;
1.46 moko 141: HASH_PUT_CSTR(hash, "PeakPagefileUsage", new VDouble(d1));
1.16 paf 142: }
143: }
1.17 paf 144: FreeLibrary(hMod);
145: }
1.16 paf 146:
147: #else
148:
149: #ifdef HAVE_GETRUSAGE
1.17 paf 150: struct rusage u;
151: if(getrusage(RUSAGE_SELF,&u)<0)
1.39 moko 152: throw Exception(0, 0, "getrusage failed (#%d)", errno);
1.17 paf 153:
1.46 moko 154: HASH_PUT_CSTR(hash, "utime", new VDouble(u.ru_utime.tv_sec+u.ru_utime.tv_usec/1000000.0));
155: HASH_PUT_CSTR(hash, "stime", new VDouble(u.ru_stime.tv_sec+u.ru_stime.tv_usec/1000000.0));
156: HASH_PUT_CSTR(hash, "maxrss", new VDouble(u.ru_maxrss));
157: HASH_PUT_CSTR(hash, "ixrss", new VDouble(u.ru_ixrss));
158: HASH_PUT_CSTR(hash, "idrss", new VDouble(u.ru_idrss));
159: HASH_PUT_CSTR(hash, "isrss", new VDouble(u.ru_isrss));
1.16 paf 160: #endif
1.13 paf 161:
1.40 moko 162: #endif
163:
1.17 paf 164: struct timeval tp;
165: if(gettimeofday(&tp, NULL)<0)
1.38 moko 166: throw Exception(0, 0, "gettimeofday failed (#%d)", errno);
1.17 paf 167:
1.46 moko 168: HASH_PUT_CSTR(hash, "tv_sec", new VDouble(tp.tv_sec));
169: HASH_PUT_CSTR(hash, "tv_usec", new VDouble(tp.tv_usec));
1.1 paf 170:
1.17 paf 171: return rusage;
172: }
173:
174: #ifndef PA_DEBUG_DISABLE_GC
175: Value& memory_element() {
176: VHash& memory=*new VHash;
177: HashStringValue& hash=memory.hash();
178: size_t heap_size=GC_get_heap_size();
179: size_t free_bytes=GC_get_free_bytes();
180: size_t bytes_since_gc=GC_get_bytes_since_gc();
181: size_t total_bytes=GC_get_total_bytes();
182:
1.46 moko 183: HASH_PUT_CSTR(hash, "used", new VDouble((heap_size-free_bytes)/1024.0));
184: HASH_PUT_CSTR(hash, "free", new VDouble(free_bytes/1024.0));
185: HASH_PUT_CSTR(hash, "ever_allocated_since_compact", new VDouble(bytes_since_gc/1024.0));
186: HASH_PUT_CSTR(hash, "ever_allocated_since_start", new VDouble(total_bytes/1024.0));
1.17 paf 187:
188: return memory;
189: }
1.16 paf 190: #endif
191:
1.44 moko 192: extern const char* parser3_mode;
1.45 moko 193: const char *parser3_log_filespec();
1.44 moko 194:
1.47 moko 195: #ifndef _MSC_VER
196: static int get_rlimit_resource(const String& aname) {
197: if(aname=="limit-cpu")
198: return RLIMIT_CPU;
199: else if(aname=="limit-mem")
200: return RLIMIT_DATA;
201: else // limit-nproc
202: return RLIMIT_NPROC;
203: }
204: #endif
205:
1.27 misha 206: Value* VStatus::get_element(const String& aname) {
1.50 moko 207: MAYBE_GET_SPECIAL(VStateless_class::get_element(aname));
1.33 moko 208:
1.17 paf 209: // getstatus
1.22 paf 210: if(Cache_manager* manager=cache_managers->get(aname))
1.17 paf 211: return manager->get_status();
212:
1.23 paf 213: if(aname=="pid")
214: return new VInt(getpid());
215:
216: if(aname=="tid")
217: return new VInt(pa_get_thread_id());
218:
1.44 moko 219: if(aname=="mode")
220: return new VString(*new String(parser3_mode));
221:
1.51 ! moko 222: // in parallel mode it is the value when the connection was accepted
! 223: if(aname=="connections")
! 224: return new VInt(HTTPD_Server::connections);
! 225:
1.45 moko 226: if(aname=="log-filename")
227: return new VString(*new String(pa_strdup(parser3_log_filespec())));
228:
1.17 paf 229: if(aname=="rusage")
230: return &rusage_element();
231:
232: #ifndef PA_DEBUG_DISABLE_GC
233: if(aname=="memory")
234: return &memory_element();
235: #endif
1.1 paf 236:
1.47 moko 237: #ifndef _MSC_VER
238: if(aname=="limit-cpu" || aname=="limit-mem" || aname=="limit-nproc") {
239: struct rlimit rlim;
240: if(getrlimit(get_rlimit_resource(aname), &rlim)<0)
241: throw Exception(0, 0, "getrlimit failed: %s (%d)", strerror(errno), errno);
242:
1.48 moko 243: return new VString(*new String(rlim.rlim_cur == RLIM_INFINITY ? "unlimited" : pa_itoa(rlim.rlim_cur)));
1.47 moko 244: }
245: #endif
1.1 paf 246: return 0;
247: }
1.47 moko 248:
249: const VJunction* VStatus::put_element(const String& aname, Value* avalue) {
250: #ifndef _MSC_VER
251: if(aname=="limit-cpu" || aname=="limit-mem" || aname=="limit-nproc") {
252: const String& value_str=avalue->as_string();
253: struct rlimit rlim;
1.48 moko 254: rlim.rlim_cur=value_str=="unlimited" ? RLIM_INFINITY : (rlim_t)pa_atoul(value_str.cstr(), 0, &value_str);
1.47 moko 255: rlim.rlim_max=rlim.rlim_cur;
256:
257: if(setrlimit(get_rlimit_resource(aname), &rlim)<0)
1.48 moko 258: throw Exception(0, 0, "setrlimit %s failed: %s (%d)", value_str.cstr(), strerror(errno), errno);
1.47 moko 259:
260: return 0;
261: }
262: #endif
263: return Value::put_element(aname, avalue);
264: }
E-mail: