sg_error sg_vector_clone_into(sg_vector **dest, const sg_vector *src){ if( !dest ) { RETURN_WITH_SET_ERROR( "vector", SG_ERROR_INVALID_ARGUMENT, "dest" ); } if( !src ) { if(*dest) { sg_vector_free(*dest); *dest = NULL; } return SG_ERROR_NONE; } if(SG_ERROR_NONE != sg_prove_vector(src)) { RETURN_WITH_SET_ERROR( "vector", SG_ERROR_INVALID_ARGUMENT, "src" ); } if( !*dest ) { *dest = sg_vector_clone( src ); if( *dest ) return SG_ERROR_NONE; } else if( ( SG_ERROR_NONE == sg_prove_vector(*dest) ) && ( SG_ERROR_NONE == sg_prove_vector_compat(*dest, src) ) && ( SG_ERROR_NONE == sg_vector_clone_into_int( dest, src ) ) ) { return SG_ERROR_NONE; } sg_vector_free(*dest); *dest = NULL; return sg_get_error(); }
static sg_error sg_get_page_stats_diff_int(sg_page_stats *tgt, const sg_page_stats *now, const sg_page_stats *last){ if( NULL == tgt ) { RETURN_WITH_SET_ERROR("page", SG_ERROR_INVALID_ARGUMENT, "sg_get_page_stats_diff_int(tgt)"); } if( now ) { *tgt = *now; if( last ) { tgt->pages_pagein -= last->pages_pagein; tgt->pages_pageout -= last->pages_pageout; tgt->systime -= last->systime; } } else { memset(tgt, 0, sizeof(*tgt)); } return SG_ERROR_NONE; }
static sg_error sg_get_mem_stats_int(sg_mem_stats *mem_stats_buf) { #ifdef HPUX struct pst_static pstat_static; struct pst_dynamic pstat_dynamic; #elif defined(SOLARIS) # ifdef _SC_PHYS_PAGES long phystotal; long physav; # else kstat_ctl_t *kc; kstat_t *ksp; kstat_named_t *kn; # endif #elif defined(LINUX) || defined(CYGWIN) #define LINE_BUF_SIZE 256 char *line_ptr, line_buf[LINE_BUF_SIZE]; long long value; FILE *f; #elif defined(HAVE_HOST_STATISTICS) || defined(HAVE_HOST_STATISTICS64) # if defined(HAVE_HOST_STATISTICS64) struct vm_statistics64 vm_stats; # else struct vm_statistics vm_stats; # endif mach_msg_type_number_t count; kern_return_t rc; #elif defined(HAVE_STRUCT_UVMEXP_SYSCTL) && defined(VM_UVMEXP2) int mib[2]; struct uvmexp_sysctl uvm; size_t size = sizeof(uvm); #elif defined(HAVE_STRUCT_UVMEXP) && defined(VM_UVMEXP) int mib[2]; struct uvmexp uvm; size_t size = sizeof(uvm); #elif defined(FREEBSD) || defined(DFBSD) size_t size; unsigned int total_count; unsigned int free_count; unsigned int cache_count; unsigned int inactive_count; #elif defined(HAVE_STRUCT_VMTOTAL) struct vmtotal vmtotal; size_t size; #if defined(HW_PHYSMEM) || defined(HW_USERMEM) int mib[2]; # if defined(HW_PHYSMEM) u_long total_mem; # endif # if defined(HW_USERMEM) u_long user_mem; # endif #endif #elif defined(AIX) perfstat_memory_total_t mem; #elif defined(WIN32) MEMORYSTATUSEX memstats; #endif #if defined(HPUX) if (pstat_getdynamic(&pstat_dynamic, sizeof(pstat_dynamic), 1, 0) == -1) { RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_PSTAT, "pstat_dynamic"); } /* * from man pstat_getstatic: * * pstat_getstatic() returns information about the system. Although * this data usually does not change frequently, it may change while * the system is running due to manually or automatically generated * administrative changes in the associated kernel tunables, online * addition/deletion of resources, or other events. There is one * global instance of this context. * * ==> Can't hold this value globally static. */ if( pstat_getstatic(&pstat_static, sizeof(pstat_static), 1, 0) == -1 ) { RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_PSTAT, "pstat_static"); } mem_stats_buf->total = ((long long) pstat_static.physical_memory) * pstat_static.page_size; mem_stats_buf->free = ((long long) pstat_dynamic.psd_free) * pstat_static.page_size; mem_stats_buf->used = mem_stats_buf->total - mem_stats_buf->free; #elif defined(AIX) /* return code is number of structures returned */ if(perfstat_memory_total(NULL, &mem, sizeof(perfstat_memory_total_t), 1) != 1) { RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTLBYNAME, "perfstat_memory_total"); } mem_stats_buf->total = (unsigned long long) mem.real_total; mem_stats_buf->total *= sys_page_size; mem_stats_buf->used = (unsigned long long) mem.real_inuse; mem_stats_buf->used *= sys_page_size; mem_stats_buf->cache = (unsigned long long) mem.numperm; mem_stats_buf->cache *= sys_page_size; mem_stats_buf->free = (unsigned long long) mem.real_free; mem_stats_buf->free *= sys_page_size; #elif defined(SOLARIS) # ifdef _SC_PHYS_PAGES if( ( phystotal = sysconf(_SC_PHYS_PAGES) ) < 0 ) { RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCONF, "_SC_PHYS_PAGES"); } if( ( physav = sysconf(_SC_AVPHYS_PAGES) ) < 0 ) { RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCONF, "_SC_AVPHYS_PAGES"); } mem_stats_buf->total = ((unsigned long long)phystotal) * ((unsigned long long)sys_page_size); mem_stats_buf->free = ((unsigned long long)physav) * ((unsigned long long)sys_page_size); # else if( (kc = kstat_open()) == NULL ) { RETURN_WITH_SET_ERROR("mem", SG_ERROR_KSTAT_OPEN, NULL); } if((ksp=kstat_lookup(kc, "unix", 0, "system_pages")) == NULL) { RETURN_WITH_SET_ERROR("mem", SG_ERROR_KSTAT_LOOKUP, "unix,0,system_pages"); } if (kstat_read(kc, ksp, 0) == -1) { RETURN_WITH_SET_ERROR("mem", SG_ERROR_KSTAT_READ, NULL); } if((kn=kstat_data_lookup(ksp, "physmem")) == NULL) { RETURN_WITH_SET_ERROR("mem", SG_ERROR_KSTAT_DATA_LOOKUP, "physmem"); } mem_stats_buf->total = ((unsigned long long)kn->value.ul) * ((unsigned long long)sys_page_size); if((kn=kstat_data_lookup(ksp, "freemem")) == NULL) { RETURN_WITH_SET_ERROR("mem", SG_ERROR_KSTAT_DATA_LOOKUP, "freemem"); } mem_stats_buf->free = ((unsigned long long)kn->value.ul) * ((unsigned long long)sys_page_size); kstat_close(kc); # endif mem_stats_buf->used = mem_stats_buf->total - mem_stats_buf->free; mem_stats_buf->cache = 0; #elif defined(LINUX) || defined(CYGWIN) if ((f = fopen("/proc/meminfo", "r")) == NULL) { RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_OPEN, "/proc/meminfo"); } #define MEM_TOTAL_PREFIX "MemTotal:" #define MEM_FREE_PREFIX "MemFree:" #define MEM_CACHED_PREFIX "Cached:" while ((line_ptr = fgets(line_buf, sizeof(line_buf), f)) != NULL) { if ( sscanf(line_buf, "%*s %lld kB", &value) != 1) continue; if (strncmp(line_buf, MEM_TOTAL_PREFIX, sizeof(MEM_TOTAL_PREFIX) - 1) == 0) mem_stats_buf->total = value; else if (strncmp(line_buf, MEM_FREE_PREFIX, sizeof(MEM_FREE_PREFIX) - 1) == 0) mem_stats_buf->free = value; else if (strncmp(line_buf, MEM_CACHED_PREFIX, sizeof(MEM_CACHED_PREFIX) - 1) == 0) mem_stats_buf->cache = value; } mem_stats_buf->free += mem_stats_buf->cache; mem_stats_buf->total *= 1024; mem_stats_buf->free *= 1024; mem_stats_buf->cache *= 1024; #undef MEM_TOTAL_PREFIX #undef MEM_FREE_PREFIX #undef MEM_CACHED_PREFIX fclose(f); mem_stats_buf->used = mem_stats_buf->total - mem_stats_buf->free; #elif defined(HAVE_STRUCT_UVMEXP_SYSCTL) && defined(VM_UVMEXP2) mib[0] = CTL_VM; mib[1] = VM_UVMEXP2; if (sysctl(mib, 2, &uvm, &size, NULL, 0) < 0) { RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTL, "CTL_VM.VM_UVMEXP2"); } mem_stats_buf->total = uvm.npages; mem_stats_buf->cache = uvm.filepages + uvm.execpages; mem_stats_buf->free = uvm.free + mem_stats_buf->cache; mem_stats_buf->total *= uvm.pagesize; mem_stats_buf->cache *= uvm.pagesize; mem_stats_buf->free *= uvm.pagesize; mem_stats_buf->used = mem_stats_buf->total - mem_stats_buf->free; #elif defined(HAVE_STRUCT_UVMEXP) && defined(VM_UVMEXP) mib[0] = CTL_VM; mib[1] = VM_UVMEXP; if (sysctl(mib, 2, &uvm, &size, NULL, 0) < 0) { RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTL, "CTL_VM.VM_UVMEXP"); } mem_stats_buf->total = uvm.npages; mem_stats_buf->cache = 0; # if defined(HAVE_STRUCT_UVMEXP_FILEPAGES) mem_stats_buf->cache += uvm.filepages; # endif # if defined(HAVE_STRUCT_UVMEXP_EXECPAGES) mem_stats_buf->cache += uvm.execpages; # endif mem_stats_buf->free = uvm.free + mem_stats_buf->cache; mem_stats_buf->total *= uvm.pagesize; mem_stats_buf->cache *= uvm.pagesize; mem_stats_buf->free *= uvm.pagesize; mem_stats_buf->used = mem_stats_buf->total - mem_stats_buf->free; #elif defined(HAVE_HOST_STATISTICS) || defined(HAVE_HOST_STATISTICS64) # if defined(HAVE_HOST_STATISTICS64) count = HOST_VM_INFO64_COUNT; rc = host_statistics64(self_host_port, HOST_VM_INFO64, (host_info64_t)(&vm_stats), &count); # else count = HOST_VM_INFO_COUNT; rc = host_statistics(self_host_port, HOST_VM_INFO, (host_info_t)(&vm_stats), &count); # endif if( rc != KERN_SUCCESS ) { RETURN_WITH_SET_ERROR_WITH_ERRNO_CODE( "mem", SG_ERROR_MACHCALL, rc, "host_statistics" ); } /* * XXX check host_info(host_basic_info) ... for memory_size */ mem_stats_buf->free = vm_stats.free_count - vm_stats.speculative_count; mem_stats_buf->free += vm_stats.inactive_count; mem_stats_buf->free *= (size_t)sys_page_size; mem_stats_buf->total = vm_stats.active_count + vm_stats.wire_count + vm_stats.inactive_count + vm_stats.free_count; mem_stats_buf->total *= (size_t)sys_page_size; mem_stats_buf->used = mem_stats_buf->total - mem_stats_buf->free; mem_stats_buf->cache = 0; #elif defined(FREEBSD) || defined(DFBSD) /*returns pages*/ size = sizeof(total_count); if (sysctlbyname("vm.stats.vm.v_page_count", &total_count, &size, NULL, 0) < 0) { RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_page_count"); } /*returns pages*/ size = sizeof(free_count); if (sysctlbyname("vm.stats.vm.v_free_count", &free_count, &size, NULL, 0) < 0) { RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_free_count"); } size = sizeof(inactive_count); if (sysctlbyname("vm.stats.vm.v_inactive_count", &inactive_count , &size, NULL, 0) < 0) { RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_inactive_count"); } size = sizeof(cache_count); if (sysctlbyname("vm.stats.vm.v_cache_count", &cache_count, &size, NULL, 0) < 0) { RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_cache_count"); } /* Of couse nothing is ever that simple :) And I have inactive pages to * deal with too. So I'm going to add them to free memory :) */ mem_stats_buf->cache = (size_t)cache_count; mem_stats_buf->cache *= (size_t)sys_page_size; mem_stats_buf->total = (size_t)total_count; mem_stats_buf->total *= (size_t)sys_page_size; mem_stats_buf->free = (size_t)free_count + inactive_count + cache_count; mem_stats_buf->free *= (size_t)sys_page_size; mem_stats_buf->used = mem_stats_buf->total - mem_stats_buf->free; #elif defined(WIN32) memstats.dwLength = sizeof(memstats); if (!GlobalMemoryStatusEx(&memstats)) { RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_MEMSTATUS, NULL); } mem_stats_buf->free = memstats.ullAvailPhys; mem_stats_buf->total = memstats.ullTotalPhys; mem_stats_buf->used = mem_stat.total - mem_stat.free; if(read_counter_large(SG_WIN32_MEM_CACHE, &mem_stats_buf->cache)) mem_stats_buf->cache = 0; #elif defined(HAVE_STRUCT_VMTOTAL) /* The code in this section is based on the code in the OpenBSD * top utility, located at src/usr.bin/top/machine.c in the * OpenBSD source tree. * * For fun, and like OpenBSD top, we will do the multiplication * converting the memory stats in pages to bytes in base 2. */ size = sizeof(vmtotal); if (sysctl(vmtotal_mib, 2, &vmtotal, &size, NULL, 0) < 0) { RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTLBYNAME, "vm.vmtotal"); } /* Convert the raw stats to bytes, and return these to the caller */ mem_stats_buf->used = (unsigned long long)vmtotal.t_rm; /* total real mem in use */ mem_stats_buf->used *= sys_page_size; /* XXX scan top source to look how it determines cache size */ mem_stats_buf->cache = 0; /* no cache stats */ mem_stats_buf->free = (unsigned long long)vmtotal.t_free; /* free memory pages */ mem_stats_buf->free *= sys_page_size; # ifdef HW_PHYSMEM mib[0] = CTL_HW; mib[1] = HW_PHYSMEM; size = sizeof(total_mem); if (sysctl(mib, 2, &total_mem, &size, NULL, 0) < 0) { RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTL, "CTL_HW.HW_PHYSMEM"); } mem_stats_buf->total = total_mem; # else mem_stats_buf->total = (mem_stats_buf->used + mem_stats_buf->free); # endif # ifdef HW_USERMEM mib[0] = CTL_HW; mib[1] = HW_USERMEM; size = sizeof(user_mem); if (sysctl(mib, 2, &user_mem, &size, NULL, 0) < 0) { RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTL, "CTL_HW.HW_USERMEM"); } mem_stats_buf->used += total_mem - user_mem; # endif #else RETURN_WITH_SET_ERROR("mem", SG_ERROR_UNSUPPORTED, OS_TYPE); #endif mem_stats_buf->systime = time(NULL); return SG_ERROR_NONE; }
static sg_error sg_get_load_stats_int(sg_load_stats *load_stats_buf){ #ifdef HAVE_GETLOADAVG double loadav[3]; #elif defined(HPUX) struct pst_dynamic pstat_dynamic; #elif defined(AIX) perfstat_cpu_total_t all_cpu_info; int rc; #elif defined(SOLARIS) && !defined(HAVE_SYS_LOADAVG_H) kstat_ctl_t *kc; kstat_t *ksp; kstat_named_t *kn; #endif load_stats_buf->min1 = load_stats_buf->min5 = load_stats_buf->min15 = 0; #ifdef HAVE_GETLOADAVG getloadavg(loadav,3); load_stats_buf->min1=loadav[0]; load_stats_buf->min5=loadav[1]; load_stats_buf->min15=loadav[2]; #elif defined(SOLARIS) if ((kc = kstat_open()) == NULL) { RETURN_WITH_SET_ERROR("load", SG_ERROR_KSTAT_OPEN, NULL); } if((ksp=kstat_lookup(kc, "unix", 0, "system_misc")) == NULL){ kstat_close(kc); RETURN_WITH_SET_ERROR("load", SG_ERROR_KSTAT_LOOKUP, "unix,0,system_misc"); } if (kstat_read(kc, ksp, 0) == -1) { kstat_close(kc); RETURN_WITH_SET_ERROR("load", SG_ERROR_KSTAT_READ, NULL); } kstat_close(kc); if((kn=kstat_data_lookup(ksp, "avenrun_1min")) == NULL) { RETURN_WITH_SET_ERROR("load", SG_ERROR_KSTAT_DATA_LOOKUP, "avenrun_1min"); } load_stats_buf->min1 = (double)kn->value.ui32 / (double)256; if((kn=kstat_data_lookup(ksp, "avenrun_5min")) == NULL) { RETURN_WITH_SET_ERROR("load", SG_ERROR_KSTAT_DATA_LOOKUP, "avenrun_5min"); } load_stats_buf->min5 = (double)kn->value.ui32 / (double)256; if((kn=kstat_data_lookup(ksp, "avenrun_15min")) == NULL) { RETURN_WITH_SET_ERROR("load", SG_ERROR_KSTAT_DATA_LOOKUP, "avenrun_15min"); } load_stats_buf->min15 = (double)kn->value.ui32 / (double)256; #elif defined(HPUX) if (pstat_getdynamic(&pstat_dynamic, sizeof(pstat_dynamic), 1, 0) == -1) { RETURN_WITH_SET_ERROR_WITH_ERRNO("load", SG_ERROR_PSTAT, "pstat_dynamic"); } load_stats_buf->min1=pstat_dynamic.psd_avg_1_min; load_stats_buf->min5=pstat_dynamic.psd_avg_5_min; load_stats_buf->min15=pstat_dynamic.psd_avg_15_min; #elif defined(AIX) rc = perfstat_cpu_total( NULL, &all_cpu_info, sizeof(all_cpu_info), 1); if( -1 == rc ) { RETURN_WITH_SET_ERROR_WITH_ERRNO("load", SG_ERROR_PSTAT, "perfstat_cpu_total"); } else { load_stats_buf->min1 = (double) all_cpu_info.loadavg[0] / (double)(1 << SBITS); load_stats_buf->min5 = (double) all_cpu_info.loadavg[1] / (double)(1 << SBITS); load_stats_buf->min15 = (double) all_cpu_info.loadavg[2] / (double)(1 << SBITS); } #else RETURN_WITH_SET_ERROR("load", SG_ERROR_UNSUPPORTED, OS_TYPE); #endif load_stats_buf->systime = time(NULL); return SG_ERROR_NONE; }
static sg_error sg_get_user_stats_int(sg_vector **user_stats_vector_ptr) { size_t num_users = 0; sg_user_stats *user_ptr; time_t now = time(NULL); #if defined (WIN32) LPWKSTA_USER_INFO_0 buf = NULL; LPWKSTA_USER_INFO_0 tmp_buf; unsigned long entries_read = 0; unsigned long entries_tot = 0; unsigned long resumehandle = 0; NET_API_STATUS nStatus; int i; char name[256]; #undef VECTOR_UPDATE_ERROR_CLEANUP #define VECTOR_UPDATE_ERROR_CLEANUP if (buf != NULL) NetApiBufferFree(buf); do { nStatus = NetWkstaUserEnum(NULL, 0, (LPBYTE*)&buf, MAX_PREFERRED_LENGTH, &entries_read, &entries_tot, &resumehandle); if((nStatus == NERR_Success) || (nStatus == ERROR_MORE_DATA)) { if((tmp_buf = buf) == NULL) continue; for( i = 0; i < entries_read; ++i ) { /* assert(tmp_buf != NULL); */ if( tmp_buf == NULL ) { sg_set_error(SG_ERROR_PERMISSION, "User list"); ERROR_LOG("user", "Permission denied fetching user details"); break; /* XXX break and not return? */ } /* It's in unicode. We are not. Convert */ WideCharToMultiByte(CP_ACP, 0, tmp_buf->wkui0_username, -1, name, sizeof(name), NULL, NULL); VECTOR_UPDATE(user_stats_vector_ptr, num_users + 1, user_ptr, sg_user_stats); if( SG_ERROR_NONE != sg_update_string( &user_ptr[num_users].login_name, name ) ) { VECTOR_UPDATE_ERROR_CLEANUP RETURN_FROM_PREVIOUS_ERROR( "user", sg_get_error() ); } user_ptr[num_users].systime = now; ++tmp_buf; ++num_users; } } else { RETURN_WITH_SET_ERROR("user", SG_ERROR_PERMISSION, "User enum"); } if (buf != NULL) { NetApiBufferFree(buf); buf=NULL; } } while (nStatus == ERROR_MORE_DATA); if (buf != NULL) NetApiBufferFree(buf); #elif defined(CAN_USE_UTMPX) || defined(CAN_USE_UTMP) #define SG_LUPDATE_IF(tgt,obj,memb) \ (((void *)(&(obj->memb))) == ((void *)(&(obj->memb[0])))) \ ? sg_lupdate_string(tgt, obj->memb, sizeof(obj->memb))\ : sg_update_string(tgt, obj->memb) #define UTMP_MUTEX_NAME "utmp" #undef VECTOR_UPDATE_ERROR_CLEANUP # if defined(CAN_USE_UTMPX) struct utmpx *utx; # endif # if defined(CAN_USE_UTMP) struct utmp *ut; # endif /* following block contains code for utmpx */ # if defined(CAN_USE_UTMPX) # ifdef ENABLE_THREADS # define VECTOR_UPDATE_ERROR_CLEANUP endutxent(); sg_unlock_mutex(UTMP_MUTEX_NAME); sg_lock_mutex(UTMP_MUTEX_NAME); # else # define VECTOR_UPDATE_ERROR_CLEANUP endutxent(); # endif setutxent(); while( NULL != (utx = getutxent()) ) { if( USER_PROCESS != utx->ut_type ) continue; VECTOR_UPDATE(user_stats_vector_ptr, num_users + 1, user_ptr, sg_user_stats); if( ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].login_name, utx, ut_user ) ) || # if defined(HAVE_UTMPX_HOST) # if defined(HAVE_UTMPX_SYSLEN) ( SG_ERROR_NONE != sg_lupdate_string( &user_ptr[num_users].hostname, utx->ut_host, utx->ut_syslen + 1 ) ) || # else ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].hostname, utx, ut_host ) ) || # endif # endif ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].device, utx, ut_line ) ) || ( SG_ERROR_NONE != sg_update_mem( (void *)(&user_ptr[num_users].record_id), utx->ut_id, sizeof(utx->ut_id) ) ) ) { VECTOR_UPDATE_ERROR_CLEANUP RETURN_FROM_PREVIOUS_ERROR( "user", sg_get_error() ); } user_ptr[num_users].record_id_size = sizeof(utx->ut_id); user_ptr[num_users].pid = utx->ut_pid; user_ptr[num_users].login_time = utx->ut_tv.tv_sec; user_ptr[num_users].systime = now; ++num_users; } endutxent(); if(!num_users) { # endif /* following block contains code for utmp */ # if defined(CAN_USE_UTMP) # undef VECTOR_UPDATE_ERROR_CLEANUP # ifdef ENABLE_THREADS # define VECTOR_UPDATE_ERROR_CLEANUP endutent(); sg_unlock_mutex(UTMP_MUTEX_NAME); # else # define VECTOR_UPDATE_ERROR_CLEANUP endutent(); # endif setutent(); while( NULL != (ut = getutent()) ) { # ifdef HAVE_UTMP_TYPE if( USER_PROCESS != ut->ut_type ) continue; # elif defined(HAVE_UTMP_NAME) if (ut->ut_name[0] == '\0') continue; # elif defined(HAVE_UTMP_USER) if (ut->ut_user[0] == '\0') continue; # endif VECTOR_UPDATE(user_stats_vector_ptr, num_users + 1, user_ptr, sg_user_stats); if( ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].device, ut, ut_line ) ) # if defined(HAVE_UTMP_USER) || ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].login_name, ut, ut_user ) ) # elif defined(HAVE_UTMP_NAME) || ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].login_name, ut, ut_name ) ) # endif # if defined(HAVE_UTMP_HOST) || ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].hostname, ut, ut_host ) ) # endif # if defined(HAVE_UTMP_ID) || ( SG_ERROR_NONE != sg_update_mem( (void **)(&user_ptr[num_users].record_id), ut->ut_id, sizeof(ut->ut_id) ) ) # endif ) { VECTOR_UPDATE_ERROR_CLEANUP RETURN_FROM_PREVIOUS_ERROR( "user", sg_get_error() ); } # if defined(HAVE_UTMP_ID) user_ptr[num_users].record_id_size = sizeof(ut->ut_id); # endif # if defined(HAVE_UTMP_PID) user_ptr[num_users].pid = ut->ut_pid; # endif #if defined(HAVE_UTMP_TIME) user_ptr[num_users].login_time = ut->ut_time; #endif user_ptr[num_users].systime = now; ++num_users; } endutent(); # endif # if defined(CAN_USE_UTMPX) } #endif # ifdef ENABLE_THREADS sg_unlock_mutex(UTMP_MUTEX_NAME); # endif #elif defined(HAVE_STRUCT_UTMP) && defined(_PATH_UTMP) struct utmp entry; FILE *f; if ((f=fopen(_PATH_UTMP, "r")) == NULL) { RETURN_WITH_SET_ERROR_WITH_ERRNO("user", SG_ERROR_OPEN, _PATH_UTMP); } #ifdef SG_LUPDATE_IF #undef SG_LUPDATE_IF #endif #define SG_LUPDATE_IF(tgt,obj,memb) \ (((void *)(&(obj.memb))) == ((void *)(&(obj.memb[0])))) \ ? sg_lupdate_string(tgt, obj.memb, sizeof(obj.memb))\ : sg_update_string(tgt, obj.memb) #undef VECTOR_UPDATE_ERROR_CLEANUP #define VECTOR_UPDATE_ERROR_CLEANUP fclose(f); while((fread(&entry, sizeof(entry),1,f)) != 0){ #ifdef HAVE_UTMP_TYPE if( USER_PROCESS != ut->ut_type ) continue; #elif defined(HAVE_UTMP_NAME) if (entry.ut_name[0] == '\0') continue; #elif defined(HAVE_UTMP_USER) if (entry.ut_user[0] == '\0') continue; #endif VECTOR_UPDATE(user_stats_vector_ptr, num_users + 1, user_ptr, sg_user_stats); if( ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].device, entry, ut_line ) ) #if defined(HAVE_UTMP_USER) || ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].login_name, entry, ut_user ) ) #elif defined(HAVE_UTMP_NAME) || ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].login_name, entry, ut_name ) ) #endif #if defined(HAVE_UTMP_HOST) || ( SG_ERROR_NONE != SG_LUPDATE_IF( &user_ptr[num_users].hostname, entry, ut_host ) ) #endif #if defined(HAVE_UTMP_ID) || ( SG_ERROR_NONE != sg_update_mem( &user_ptr[num_users].record_id, entry.ut_id, sizeof(entry.ut_id) ) ) #endif ) { VECTOR_UPDATE_ERROR_CLEANUP RETURN_FROM_PREVIOUS_ERROR( "user", sg_get_error() ); } #if defined(HAVE_UTMP_ID) user_ptr[num_users].record_id_size = sizeof(entry.ut_id); #endif #if defined(HAVE_UTMP_PID) user_ptr[num_users].pid = entry.ut_pid; #endif #if defined(HAVE_UTMP_TIME) user_ptr[num_users].login_time = entry.ut_time; #endif user_ptr[num_users].systime = now; ++num_users; } fclose(f); #else RETURN_WITH_SET_ERROR("user", SG_ERROR_UNSUPPORTED, OS_TYPE); #endif return SG_ERROR_NONE; }
sg_error sg_vector_compute_diff(sg_vector **dest_vector_ptr, const sg_vector *cur_vector, const sg_vector *last_vector) { if( NULL == dest_vector_ptr ) { RETURN_WITH_SET_ERROR("vector", SG_ERROR_INVALID_ARGUMENT, "sg_vector_compute_diff(dest_vector_ptr)"); } if( cur_vector ) { sg_error rc = sg_vector_clone_into( dest_vector_ptr, cur_vector ); /* proves *dest, cur */ if( SG_ERROR_NONE != rc ) { RETURN_FROM_PREVIOUS_ERROR( "vector", rc ); } if( NULL == *dest_vector_ptr ) return SG_ERROR_NONE; assert( cur_vector->info.compute_diff_fn ); assert( cur_vector->info.compare_fn ); TRACE_LOG_FMT("vector", "computing vector diff between vector containing %lu items (cur) and vector containing %lu items (last)", cur_vector->used_count, last_vector ? last_vector->used_count : 0 ); if( last_vector && ( SG_ERROR_NONE == sg_prove_vector(last_vector) ) && ( SG_ERROR_NONE == sg_prove_vector_compat(cur_vector, last_vector ) ) ) { size_t i, item_size = last_vector->info.item_size; unsigned matched[(cur_vector->used_count / (8 * sizeof(unsigned))) + 1]; char *diff = VECTOR_DATA(*dest_vector_ptr); char const *last = VECTOR_DATA_CONST(last_vector); memset( matched, 0, sizeof(matched) ); for( i = 0; i < (*dest_vector_ptr)->used_count; ++i ) { size_t j; for( j = 0; j < last_vector->used_count; ++j ) { if( BIT_ISSET(matched, j) ) /* already matched? */ continue; if (last_vector->info.compare_fn(last + j * item_size, diff + i * item_size) == 0) { BIT_SET(matched, j); last_vector->info.compute_diff_fn(last + j * item_size, diff + i * item_size); } } if( j == last_vector->used_count ) { /* We have lost an item since last time - skip */ } } /* XXX append the items lost since last run? */ } } else { sg_vector_free(*dest_vector_ptr); *dest_vector_ptr = NULL; RETURN_WITH_SET_ERROR("vector", SG_ERROR_INVALID_ARGUMENT, "sg_vector_compute_diff(cur_vector)"); } return SG_ERROR_NONE; }
static sg_error sg_get_host_info_int(sg_host_info *host_info_buf) { #ifdef WIN32 unsigned long nameln; char *name; long long result; OSVERSIONINFOEX osinfo; SYSTEM_INFO sysinfo; char *tmp_name; char tmp[10]; #else struct utsname os; # if defined(HPUX) struct pst_static pstat_static; struct pst_dynamic pstat_dynamic; time_t currtime; long boottime; # elif defined(SOLARIS) time_t boottime, curtime; kstat_ctl_t *kc; kstat_t *ksp; kstat_named_t *kn; char *isainfo = NULL; long isabufsz, rc; # elif defined(LINUX) || defined(CYGWIN) FILE *f; # elif defined(ALLBSD) int mib[2]; struct timeval boottime; time_t curtime; size_t size; int ncpus; # if defined(HW_MACHINE_ARCH) || defined(HW_MACHINE) char arch_name[16]; # endif # elif defined(AIX) static perfstat_cpu_total_t cpu_total; sg_error rc; # if defined(HAVE_GETUTXENT) struct utmpx *ut; # else struct utmp *ut; # endif # endif #endif host_info_buf->ncpus = 0; host_info_buf->maxcpus = 0; host_info_buf->bitwidth = 0; host_info_buf->host_state = sg_unknown_configuration; host_info_buf->uptime = 0; host_info_buf->systime = 0; #ifdef WIN32 /* these settings are static after boot, so why get them * constantly? * * Because we want to know some changes anyway - at least * when the hostname (DNS?) changes */ /* get system name */ nameln = MAX_COMPUTERNAME_LENGTH + 1; name = sg_malloc(nameln); if(name == NULL) { RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() ); } /* * XXX probably GetComputerNameEx() is a better entry point ... */ if( GetComputerName(name, &nameln) == 0 ) { free(name); RETURN_WITH_SET_ERROR("os", SG_ERROR_HOST, "GetComputerName"); } if(SG_ERROR_NONE != sg_update_string(&host_info_buf->hostname, name)) { free(name); RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() ); } free(name); /* get OS name, version and build */ ZeroMemory(&osinfo, sizeof(OSVERSIONINFOEX)); osinfo.dwOSVersionInfoSize = sizeof(osinfo); if(!GetVersionEx(&osinfo)) { RETURN_WITH_SET_ERROR("os", SG_ERROR_HOST, "GetVersionEx"); } GetSystemInfo(&sysinfo); /* Release - single number */ if(snprintf(tmp, sizeof(tmp), "%ld", osinfo.dwBuildNumber) == -1) { RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SPRINTF, NULL); } if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_release, tmp)) { RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() ); } /* Version */ /* usually a single digit . single digit, eg 5.0 */ if(snprintf(tmp, sizeof(tmp), "%ld.%ld", osinfo.dwMajorVersion, osinfo.dwMinorVersion) == -1) { RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() ); } if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_version, tmp)) { RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() ); } /* OS name */ tmp_name = get_os_name(osinfo, sysinfo); if(tmp_name == NULL) { RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() ); } if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_name, tmp_name)) { free(tmp_name); RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() ); } free(tmp_name); /* Platform */ switch(sysinfo.wProcessorArchitecture) { case PROCESSOR_ARCHITECTURE_INTEL: if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform, "Intel")) { RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() ); } break; case PROCESSOR_ARCHITECTURE_IA64: if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform, "IA64")) { RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() ); } break; case PROCESSOR_ARCHITECTURE_AMD64: if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform, "AMD64")) { RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() ); } break; default: if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform, "Unknown")){ RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() ); } break; } if(read_counter_large(SG_WIN32_UPTIME, &result)) { RETURN_WITH_SET_ERROR("os", SG_ERROR_PDHREAD, PDH_UPTIME); } host_info_buf->uptime = (time_t) result; #else if((uname(&os)) < 0) { RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_UNAME, NULL); } if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_name, os.sysname)) { RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() ); } if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_release, os.release)) { RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() ); } if(SG_ERROR_NONE != sg_update_string(&host_info_buf->os_version, os.version)) { RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() ); } if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform, os.machine)) { RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() ); } if(SG_ERROR_NONE != sg_update_string(&host_info_buf->hostname, os.nodename)) { RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() ); } /* get uptime */ #ifdef HPUX if (pstat_getstatic(&pstat_static, sizeof(pstat_static), 1, 0) == -1) { RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_PSTAT, "pstat_static"); } if (pstat_getdynamic(&pstat_dynamic, sizeof(pstat_dynamic), 1, 0) == -1) { RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_PSTAT, "pstat_dynamic"); } currtime = time(NULL); boottime = pstat_static.boot_time; host_info_buf->uptime = currtime - boottime; host_info_buf->ncpus = pstat_dynamic.psd_proc_cnt; host_info_buf->maxcpus = pstat_dynamic.psd_max_proc_cnt; host_info_buf->bitwidth = sysconf(_SC_KERNEL_BITS); /* * TODO: getting virtualization state * 1) on boostrapping this component, try loading /opt/hpvm/lib/libhpvm.so (or so) * 2) get function addresses for * a) HPVM_boolean hpvm_api_server_check() * b) HPVM_boolean hpvm_api_virtmach_check() * * Seems to be hardware virtualization ... * See: http://docstore.mik.ua/manuals/hp-ux/en/T2767-90141/index.html (hpvmpubapi(3)) * http://jreypo.wordpress.com/tag/hpvm/ * http://jreypo.wordpress.com/category/hp-ux/page/3/ * http://h20338.www2.hp.com/enterprise/us/en/os/hpux11i-partitioning-integrity-vm.html */ #elif defined(SOLARIS) if ((kc = kstat_open()) == NULL) { RETURN_WITH_SET_ERROR("os", SG_ERROR_KSTAT_OPEN, NULL); } if((ksp=kstat_lookup(kc, "unix", -1, "system_misc"))==NULL){ kstat_close(kc); RETURN_WITH_SET_ERROR("os", SG_ERROR_KSTAT_LOOKUP, "unix,-1,system_misc"); } if (kstat_read(kc, ksp, 0) == -1) { kstat_close(kc); RETURN_WITH_SET_ERROR("os", SG_ERROR_KSTAT_READ, NULL); } if((kn=kstat_data_lookup(ksp, "boot_time")) == NULL){ kstat_close(kc); RETURN_WITH_SET_ERROR("os", SG_ERROR_KSTAT_DATA_LOOKUP, "boot_time"); } /* XXX verify on Solaris 10 if it's still ui32 */ boottime = (kn->value.ui32); kstat_close(kc); time(&curtime); host_info_buf->uptime = curtime - boottime; host_info_buf->ncpus = sysconf(_SC_NPROCESSORS_ONLN); host_info_buf->maxcpus = sysconf(_SC_NPROCESSORS_CONF); isainfo = sg_malloc( isabufsz = (32 * sizeof(*isainfo)) ); if( NULL == isainfo ) { RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() ); } # define MKSTR(x) #x # if defined(SI_ARCHITECTURE_K) # define SYSINFO_CMD SI_ARCHITECTURE_K # elif defined(SI_ISALIST) # define SYSINFO_CMD SI_ISALIST # else # define SYSINFO_CMD SI_ARCHITECTURE # endif sysinfo_again: if( -1 == ( rc = sysinfo( SYSINFO_CMD, isainfo, isabufsz ) ) ) { free(isainfo); RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSINFO, MKSTR(SYSINFO_CMD) ); } else if( rc > isabufsz ) { char *tmp = sg_realloc(isainfo, rc); if( NULL == tmp ) { free(isainfo); RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() ); } isabufsz = rc; isainfo = tmp; goto sysinfo_again; } host_info_buf->bitwidth = get_bitwidth_by_arch_name(isainfo); free(isainfo); host_info_buf->host_state = sg_unknown_configuration; #elif defined(LINUX) || defined(CYGWIN) if ((f=fopen("/proc/uptime", "r")) == NULL) { RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_OPEN, "/proc/uptime"); } #define TIME_T_SCANF_FMT (sizeof(int[(((time_t)-1)/2)%4+1]) == sizeof(int[1]) ? "%ld %*d" : "%lu %*d" ) if((fscanf(f,TIME_T_SCANF_FMT,&host_info_buf->uptime)) != 1){ fclose(f); RETURN_WITH_SET_ERROR("os", SG_ERROR_PARSE, NULL); } fclose(f); # if defined(LINUX) host_info_buf->ncpus = sysconf(_SC_NPROCESSORS_ONLN); host_info_buf->maxcpus = sysconf(_SC_NPROCESSORS_CONF); if( access( "/proc/sys/kernel/vsyscall64", F_OK ) == 0 || access( "/proc/sys/abi/vsyscall32", F_OK ) == 0 ) { host_info_buf->bitwidth = 64; } else { host_info_buf->bitwidth = sysconf(_SC_LONG_BIT); // well, maybe 64-bit disabled 128-bit system o.O } host_info_buf->host_state = sg_unknown_configuration; # endif #elif defined(ALLBSD) mib[0] = CTL_KERN; mib[1] = KERN_BOOTTIME; size = sizeof(boottime); if (sysctl(mib, 2, &boottime, &size, NULL, 0) < 0) { RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_KERN.KERN_BOOTTIME"); } time(&curtime); host_info_buf->uptime= curtime - boottime.tv_sec; # if defined(HW_NCPU) mib[0] = CTL_HW; mib[1] = HW_NCPU; size = sizeof(int); if( sysctl( mib, 2, &ncpus, &size, NULL, 0 ) < 0 ) { RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_HW.HW_NCPU" ); } # endif # if defined(HW_MACHINE_ARCH) mib[0] = CTL_HW; mib[1] = HW_MACHINE_ARCH; size = sizeof(arch_name); if( sysctl( mib, 2, arch_name, &size, NULL, 0 ) == 0 ) { host_info_buf->bitwidth = get_bitwidth_by_arch_name(arch_name); } else { # endif # if defined(HW_MACHINE) mib[0] = CTL_HW; mib[1] = HW_MACHINE; size = sizeof(arch_name); if( sysctl( mib, 2, arch_name, &size, NULL, 0 ) == 0 ) { host_info_buf->bitwidth = get_bitwidth_by_arch_name(arch_name); } else { SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_HW.HW_MACHINE" ); } # elif defined(HW_MACHINE_ARCH) SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_HW.HW_MACHINE_ARCH" ); # endif # if defined(HW_MACHINE_ARCH) } # endif host_info_buf->host_state = sg_unknown_configuration; /* details must be analysed "manually", no syscall */ host_info_buf->maxcpus = (unsigned)ncpus; # if defined(HW_NCPUONLINE) /* use knowledge about number of cpu's online, when available instead of assuming all of them */ mib[0] = CTL_HW; mib[1] = HW_NCPUONLINE; size = sizeof(int); if( sysctl( mib, 2, &ncpus, &size, NULL, 0 ) < 0 ) { RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "CTL_HW.HW_NCPUONLINE" ); } # endif host_info_buf->ncpus = (unsigned)ncpus; #elif defined(AIX) if(perfstat_cpu_total(NULL, &cpu_total, sizeof(cpu_total), 1) != 1) { RETURN_WITH_SET_ERROR_WITH_ERRNO("os", SG_ERROR_SYSCTL, "perfstat_cpu_total"); } if(SG_ERROR_NONE != sg_update_string(&host_info_buf->platform, cpu_total.description)) { RETURN_FROM_PREVIOUS_ERROR( "os", sg_get_error() ); } host_info_buf->ncpus = cpu_total.ncpus; host_info_buf->maxcpus = cpu_total.ncpus_cfg; host_info_buf->bitwidth = sysconf(_SC_AIX_KERNEL_BITMODE); if( sysconf(_SC_LPAR_ENABLED) > 0 ) { host_info_buf->host_state = sg_hardware_virtualized; } else { host_info_buf->host_state = sg_physical_host; } #ifdef ENABLE_THREADS if( SG_ERROR_NONE != ( rc = sg_lock_mutex("utmp") ) ) { RETURN_FROM_PREVIOUS_ERROR( "os", rc ); } #endif # if defined(HAVE_GETUTXENT) # define UTENTFN getutxent # define UTENTTM ut->ut_tv.tv_sec setutxent(); # else # define UTENTFN getutent # define UTENTTM ut->ut_time setutent(); # endif while( NULL != ( ut = UTENTFN() ) ) { if( ut->ut_type == BOOT_TIME ) { host_info_buf->uptime = time(NULL) - UTENTTM; break; } } # if defined(HAVE_GETUTXENT) endutxent(); # else endutent(); # endif #ifdef ENABLE_THREADS if( SG_ERROR_NONE != ( rc = sg_unlock_mutex("utmp") ) ) { RETURN_FROM_PREVIOUS_ERROR( "os", rc ); } #endif #else RETURN_WITH_SET_ERROR("os", SG_ERROR_UNSUPPORTED, OS_TYPE); #endif #endif /* WIN32 */ host_info_buf->systime = time(NULL); return SG_ERROR_NONE; }
static sg_error sg_get_page_stats_int(sg_page_stats *page_stats_buf){ #ifdef SOLARIS kstat_ctl_t *kc; kstat_t *ksp; cpu_stat_t cs; #elif defined(LINUX) || defined(CYGWIN) FILE *f; #define LINE_BUF_SIZE 256 char line_buf[LINE_BUF_SIZE]; #elif defined(HAVE_HOST_STATISTICS) || defined(HAVE_HOST_STATISTICS64) # if defined(HAVE_HOST_STATISTICS64) struct vm_statistics64 vm_stats; # else struct vm_statistics vm_stats; # endif mach_msg_type_number_t count; kern_return_t rc; #elif defined(HAVE_STRUCT_UVMEXP_SYSCTL) && defined(VM_UVMEXP2) int mib[2]; struct uvmexp_sysctl uvm; size_t size = sizeof(uvm); #elif defined(HAVE_STRUCT_UVMEXP) && defined(VM_UVMEXP) int mib[2]; struct uvmexp uvm; size_t size = sizeof(uvm); #elif defined(FREEBSD) || defined(DFBSD) size_t size; #elif defined(NETBSD) || defined(OPENBSD) int mib[2]; struct uvmexp uvm; size_t size = sizeof(uvm); #elif defined(AIX) perfstat_memory_total_t mem; #elif defined(HPUX) struct pst_vminfo vminfo; #endif page_stats_buf->systime = time(NULL); page_stats_buf->pages_pagein=0; page_stats_buf->pages_pageout=0; #ifdef SOLARIS if ((kc = kstat_open()) == NULL) { RETURN_WITH_SET_ERROR("page", SG_ERROR_KSTAT_OPEN, NULL); } for (ksp = kc->kc_chain; ksp!=NULL; ksp = ksp->ks_next) { if ((strcmp(ksp->ks_module, "cpu_stat")) != 0) continue; if (kstat_read(kc, ksp, &cs) == -1) continue; page_stats_buf->pages_pagein += (long long)cs.cpu_vminfo.pgpgin; page_stats_buf->pages_pageout += (long long)cs.cpu_vminfo.pgpgout; } kstat_close(kc); #elif defined(LINUX) || defined(CYGWIN) if ((f = fopen("/proc/vmstat", "r")) != NULL) { unsigned matches = 0; while( (matches < 2) && (fgets(line_buf, sizeof(line_buf), f) != NULL) ) { unsigned long long value; if (sscanf(line_buf, "%*s %llu", &value) != 1) continue; if (strncmp(line_buf, "pgpgin ", 7) == 0) { page_stats_buf->pages_pagein = value; ++matches; } else if (strncmp(line_buf, "pgpgout ", 8) == 0) { page_stats_buf->pages_pageout = value; ++matches; } } fclose(f); if( matches < 2 ) { RETURN_WITH_SET_ERROR( "page", SG_ERROR_PARSE, "/proc/vmstat" ); } } else if ((f = fopen("/proc/stat", "r")) != NULL) { if (sg_f_read_line(f, line_buf, sizeof(line_buf), "page") == NULL) { fclose(f); RETURN_FROM_PREVIOUS_ERROR( "page", sg_get_error() ); } fclose(f); if( sscanf( line_buf, "page %llu %llu", &page_stats_buf->pages_pagein, &page_stats_buf->pages_pageout ) != 2 ) { RETURN_WITH_SET_ERROR("page", SG_ERROR_PARSE, "page"); } } else { RETURN_WITH_SET_ERROR_WITH_ERRNO("page", SG_ERROR_OPEN, "/proc/stat"); } #elif defined(HAVE_HOST_STATISTICS) || defined(HAVE_HOST_STATISTICS64) self_host_port = mach_host_self(); # if defined(HAVE_HOST_STATISTICS64) count = HOST_VM_INFO64_COUNT; rc = host_statistics64(self_host_port, HOST_VM_INFO64, (host_info64_t)(&vm_stats), &count); # else count = HOST_VM_INFO_COUNT; rc = host_statistics(self_host_port, HOST_VM_INFO, (host_info_t)(&vm_stats), &count); # endif if( rc != KERN_SUCCESS ) { RETURN_WITH_SET_ERROR_WITH_ERRNO_CODE( "mem", SG_ERROR_MACHCALL, rc, "host_statistics" ); } page_stats_buf->pages_pagein = vm_stats.pageins; page_stats_buf->pages_pageout = vm_stats.pageouts; #elif defined(HAVE_STRUCT_UVMEXP_SYSCTL) && defined(VM_UVMEXP2) mib[0] = CTL_VM; mib[1] = VM_UVMEXP2; if (sysctl(mib, 2, &uvm, &size, NULL, 0) < 0) { RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTL, "CTL_VM.VM_UVMEXP2"); } page_stats_buf->pages_pagein = uvm.pgswapin; page_stats_buf->pages_pageout = uvm.pgswapout; #elif defined(HAVE_STRUCT_UVMEXP) && defined(VM_UVMEXP) mib[0] = CTL_VM; mib[1] = VM_UVMEXP; if (sysctl(mib, 2, &uvm, &size, NULL, 0) < 0) { RETURN_WITH_SET_ERROR_WITH_ERRNO("mem", SG_ERROR_SYSCTL, "CTL_VM.VM_UVMEXP"); } page_stats_buf->pages_pagein = uvm.pgswapin; page_stats_buf->pages_pageout = uvm.pgswapout; #elif defined(FREEBSD) || defined(DFBSD) size = sizeof(page_stats_buf->pages_pagein); if (sysctlbyname("vm.stats.vm.v_swappgsin", &page_stats_buf->pages_pagein, &size, NULL, 0) < 0) { RETURN_WITH_SET_ERROR_WITH_ERRNO("page", SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_swappgsin"); } size = sizeof(page_stats_buf->pages_pageout); if (sysctlbyname("vm.stats.vm.v_swappgsout", &page_stats_buf->pages_pageout, &size, NULL, 0) < 0) { RETURN_WITH_SET_ERROR_WITH_ERRNO("page", SG_ERROR_SYSCTLBYNAME, "vm.stats.vm.v_swappgsout"); } #elif defined(AIX) /* return code is number of structures returned */ if(perfstat_memory_total(NULL, &mem, sizeof(perfstat_memory_total_t), 1) != 1) { RETURN_WITH_SET_ERROR_WITH_ERRNO("page", SG_ERROR_SYSCTLBYNAME, "perfstat_memory_total"); } page_stats_buf->pages_pagein = mem.pgins; page_stats_buf->pages_pageout = mem.pgouts; #elif defined(HPUX) if( pstat_getvminfo( &vminfo, sizeof(vminfo), 1, 0 ) == -1 ) { RETURN_WITH_SET_ERROR_WITH_ERRNO("page", SG_ERROR_SYSCTLBYNAME, "pstat_getswap"); } page_stats_buf->pages_pagein = vminfo.psv_spgin; page_stats_buf->pages_pageout = vminfo.psv_spgout; #else RETURN_WITH_SET_ERROR("page", SG_ERROR_UNSUPPORTED, OS_TYPE); #endif return SG_ERROR_NONE; }
static sg_error sg_get_swap_stats_int(sg_swap_stats *swap_stats_buf) { #ifdef HPUX #define SWAP_BATCH 5 struct pst_swapinfo pstat_swapinfo[SWAP_BATCH]; int swapidx = 0; int num, i; #elif defined(SOLARIS) # if defined(HAVE_STRUCT_SWAPTABLE) struct swaptable *swtbl; int nswap, i; # elif defined(HAVE_STRUCT_ANONINFO) struct anoninfo ai; # endif #elif defined(LINUX) || defined(CYGWIN) FILE *f; #define LINE_BUF_SIZE 256 char line_buf[LINE_BUF_SIZE]; unsigned long long value; unsigned matches = 0; #elif defined(HAVE_STRUCT_XSWDEV) struct xswdev xsw; struct xswdev *xswbuf = NULL, *xswptr = NULL; int n; int mib[16]; size_t mibsize, size; #elif defined(HAVE_STRUCT_XSW_USAGE) int mib[2] = {CTL_VM, VM_SWAPUSAGE}; struct xsw_usage xsw; size_t mibsize = 2, size = sizeof(xsw); #elif defined(HAVE_STRUCT_UVMEXP_SYSCTL) && defined(VM_UVMEXP2) int mib[2] = { CTL_VM, VM_UVMEXP2 }; struct uvmexp_sysctl uvm; size_t size = sizeof(uvm); #elif defined(HAVE_STRUCT_UVMEXP) && defined(VM_UVMEXP) int mib[2] = { CTL_VM, VM_UVMEXP }; struct uvmexp uvm; size_t size = sizeof(uvm); #elif defined(ALLBSD) /* fallback if no reasonable API is supported */ struct kvm_swap swapinfo; kvm_t *kvmd; #elif defined(AIX) perfstat_memory_total_t mem; #elif defined(WIN32) MEMORYSTATUSEX memstats; #endif swap_stats_buf->total = 0; swap_stats_buf->used = 0; swap_stats_buf->free = 0; #ifdef HPUX for(;;) { num = pstat_getswap(pstat_swapinfo, sizeof pstat_swapinfo[0], SWAP_BATCH, swapidx); if (num == -1) { RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_PSTAT, "pstat_getswap"); } else if (num == 0) { break; } for (i = 0; i < num; ++i) { struct pst_swapinfo *si = &pstat_swapinfo[i]; if ((si->pss_flags & SW_ENABLED) != SW_ENABLED) continue; if ((si->pss_flags & SW_BLOCK) == SW_BLOCK) { swap_stats_buf->total += ((long long) si->pss_nblksavail) * 1024LL; swap_stats_buf->used += ((long long) si->pss_nfpgs) * 1024LL; swap_stats_buf->free = swap_stats_buf->total - swap_stats_buf->used; } if ((si->pss_flags & SW_FS) == SW_FS) { swap_stats_buf->total += ((long long) si->pss_limit) * 1024LL; swap_stats_buf->used += ((long long) si->pss_allocated) * 1024LL; swap_stats_buf->free = swap_stats_buf->total - swap_stats_buf->used; } } swapidx = pstat_swapinfo[num - 1].pss_idx + 1; } #elif defined(AIX) /* return code is number of structures returned */ if(perfstat_memory_total(NULL, &mem, sizeof(perfstat_memory_total_t), 1) != 1) { RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_SYSCTLBYNAME, "perfstat_memory_total"); } swap_stats_buf->total = ((long long)mem.pgsp_total) * sys_page_size; swap_stats_buf->free = ((long long)mem.pgsp_free) * sys_page_size; swap_stats_buf->used = swap_stats_buf->total - swap_stats_buf->free; #elif defined(SOLARIS) # if defined(HAVE_STRUCT_SWAPTABLE) again: if( ( nswap = swapctl(SC_GETNSWP, 0) ) == -1 ) { RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_SWAPCTL, NULL); } if( nswap != 0 ) { char *buf = sg_malloc( nswap * sizeof(char) * (PATH_MAX+1) + 1 ); if( NULL == buf ) { RETURN_FROM_PREVIOUS_ERROR( "swap", sg_get_error() ); } swtbl = sg_malloc( sizeof(*swtbl) + ( nswap * sizeof(swtbl->swt_ent[0]) ) ); if( NULL == swtbl ) { free(buf); RETURN_FROM_PREVIOUS_ERROR( "swap", sg_get_error() ); } memset( buf, 0, nswap * sizeof(char) * (PATH_MAX+1) + 1 ); memset( swtbl, 0, sizeof(*swtbl) + ( nswap * sizeof(swtbl->swt_ent[0]) ) ); for( i = 0; i < nswap; ++i ) swtbl->swt_ent[i].ste_path = buf + (i * (PATH_MAX+1)); swtbl->swt_n = nswap; if ((i = swapctl(SC_LIST, swtbl)) < 0) { free( buf ); free( swtbl ); RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_SWAPCTL, NULL); } if( i > nswap ) { free( swtbl ); free( buf ); goto again; } for( i = 0; i < nswap; ++i ) { swap_stats_buf->total = swtbl->swt_ent[i].ste_pages; swap_stats_buf->free = swtbl->swt_ent[i].ste_free; } free( swtbl ); free( buf ); swap_stats_buf->total *= sys_page_size; swap_stats_buf->free *= sys_page_size; swap_stats_buf->used = swap_stats_buf->total - swap_stats_buf->free; } # elif defined(HAVE_STRUCT_ANONINFO) if (swapctl(SC_AINFO, &ai) == -1) { RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_SWAPCTL, NULL); } swap_stats_buf->total = ai.ani_max; swap_stats_buf->total *= sys_page_size; swap_stats_buf->used = ai.ani_resv; swap_stats_buf->used *= sys_page_size; swap_stats_buf->free = swap_stats_buf->total - swap_stats_buf->used; # else RETURN_WITH_SET_ERROR("swap", SG_ERROR_UNSUPPORTED, OS_TYPE); # endif #elif defined(LINUX) || defined(CYGWIN) if ((f = fopen("/proc/meminfo", "r")) == NULL) { RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_OPEN, "/proc/meminfo"); } while( (matches < 2) && (fgets(line_buf, sizeof(line_buf), f) != NULL) ) { if (sscanf(line_buf, "%*s %llu kB", &value) != 1) continue; value *= 1024; if (strncmp(line_buf, "SwapTotal:", 10) == 0) { swap_stats_buf->total = value; ++matches; } else if (strncmp(line_buf, "SwapFree:", 9) == 0) { swap_stats_buf->free = value; ++matches; } } fclose(f); if( matches < 2 ) { RETURN_WITH_SET_ERROR( "swap", SG_ERROR_PARSE, "/proc/meminfo" ); } swap_stats_buf->used = swap_stats_buf->total - swap_stats_buf->free; #elif defined(HAVE_STRUCT_XSWDEV) mibsize = 2; if( swapinfo_array ) { size = 0; if( sysctl( swapinfo_mib, 2, NULL, &size, NULL, 0 ) < 0 ) { RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_SYSCTL, swapinfo_sysctl_name); } if( NULL == ( xswbuf = sg_malloc( size ) ) ) { RETURN_FROM_PREVIOUS_ERROR( "swap", sg_get_error() ); } if( sysctl( swapinfo_mib, 2, xswbuf, &size, NULL, 0 ) < 0 ) { RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_SYSCTL, swapinfo_sysctl_name); } } else { mib[0] = swapinfo_mib[0]; mib[1] = swapinfo_mib[1]; } for (n = 0; ; ++n) { if( !swapinfo_array ) { mib[mibsize] = n; size = sizeof(xsw); if (sysctl(mib, (unsigned)(mibsize + 1), &xsw, &size, NULL, 0) < 0) { if (errno == ENOENT) break; free( xswbuf ); RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_SYSCTL, swapinfo_sysctl_name); } xswptr = &xsw; } # if defined(HAVE_STRUCT_XSWDEV_SIZE) else { if( ((size_t)n) >= (size / xswbuf->xsw_size) ) break; xswptr = xswbuf + n; } if( xswptr == NULL ) { RETURN_WITH_SET_ERROR("swap", SG_ERROR_MEMSTATUS, "no swap status"); } # ifdef XSWDEV_VERSION if( xswptr->xsw_version != XSWDEV_VERSION ) { free( xswbuf ); RETURN_WITH_SET_ERROR("swap", SG_ERROR_XSW_VER_MISMATCH, NULL); } # endif # endif swap_stats_buf->total += (unsigned long long) xswptr->xsw_nblks; swap_stats_buf->used += (unsigned long long) xswptr->xsw_used; } free( xswbuf ); swap_stats_buf->total *= (size_t)sys_page_size; swap_stats_buf->used *= (size_t)sys_page_size; if( 0 == swap_stats_buf->free ) swap_stats_buf->free = swap_stats_buf->total - swap_stats_buf->used; else swap_stats_buf->free *= (size_t)sys_page_size; #elif defined(HAVE_STRUCT_XSW_USAGE) if (sysctl(mib, (unsigned)mibsize, &xsw, &size, NULL, 0) < 0) { RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_SYSCTL, "CTL_VM.VM_SWAPUSAGE" ); } swap_stats_buf->total = (unsigned long long) xsw.xsu_total; swap_stats_buf->used = (unsigned long long) xsw.xsu_used; swap_stats_buf->free = (unsigned long long) xsw.xsu_avail; #elif defined(HAVE_STRUCT_UVMEXP_SYSCTL) && defined(VM_UVMEXP2) if (sysctl(mib, 2, &uvm, &size, NULL, 0) < 0) { RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_SYSCTL, "CTL_VM.VM_UVMEXP2"); } swap_stats_buf->total = uvm.pagesize * uvm.swpages; swap_stats_buf->used = uvm.pagesize * uvm.swpginuse; /* XXX swpgonly ? */ swap_stats_buf->free = swap_stats_buf->total - swap_stats_buf->used; #elif defined(HAVE_STRUCT_UVMEXP) && defined(VM_UVMEXP) if (sysctl(mib, 2, &uvm, &size, NULL, 0) < 0) { RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_SYSCTL, "CTL_VM.VM_UVMEXP"); } swap_stats_buf->total = (unsigned long long)uvm.pagesize * (unsigned long long)uvm.swpages; swap_stats_buf->used = (unsigned long long)uvm.pagesize * (unsigned long long)uvm.swpginuse; /* XXX swpgonly ? */ swap_stats_buf->free = swap_stats_buf->total - swap_stats_buf->used; #elif defined(ALLBSD) /* XXX probably not mt-safe! */ kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, NULL); if(kvmd == NULL) { RETURN_WITH_SET_ERROR("swap", SG_ERROR_KVM_OPENFILES, NULL); } if ((kvm_getswapinfo(kvmd, &swapinfo, 1,0)) == -1) { kvm_close( kvmd ); RETURN_WITH_SET_ERROR("swap", SG_ERROR_KVM_GETSWAPINFO, NULL); } swap_stats_buf->total = (long long)swapinfo.ksw_total; swap_stats_buf->used = (long long)swapinfo.ksw_used; kvm_close( kvmd ); swap_stats_buf->total *= sys_page_size; swap_stats_buf->used *= sys_page_size; swap_stats_buf->free = swap_stats_buf->total - swap_stats_buf->used; #elif defined(WIN32) memstats.dwLength = sizeof(memstats); if (!GlobalMemoryStatusEx(&memstats)) { RETURN_WITH_SET_ERROR_WITH_ERRNO("swap", SG_ERROR_MEMSTATUS, "GloblaMemoryStatusEx"); } /* the PageFile stats include Phys memory "minus an overhead". * Due to this unknown "overhead" there's no way to extract just page * file use from these numbers */ swap_stats_buf->total = memstats.ullTotalPageFile; swap_stats_buf->free = memstats.ullAvailPageFile; swap_stats_buf->used = swap_stats_buf->total - swap_stats_buf->free; #else RETURN_WITH_SET_ERROR("swap", SG_ERROR_UNSUPPORTED, OS_TYPE); #endif swap_stats_buf->systime = time(NULL); return SG_ERROR_NONE; }