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: