#include "vserver.h"
#include "util.h"
#include "internal.h"
-#include "wrappers.h"
+
+#include <ensc_vector/vector.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>
+#define ENSC_WRAPPERS_DIRENT 1
+#define ENSC_WRAPPERS_VSERVER 1
+#define ENSC_WRAPPERS_FCNTL 1
+#define ENSC_WRAPPERS_UNISTD 1
+#include "wrappers.h"
+
#define PROC_DIR_NAME "/proc"
#define CTX_DIR_NAME "/var/run/vservers/"
#define CTX_NAME_MAX_LEN 50
int wrapper_exit_code = 1;
-struct ctx_list
+struct XidData
{
- int ctx;
- int process_count;
- int VmSize_total;
- int VmRSS_total;
- long start_time_oldest;
- long stime_total, utime_total;
- char name[CTX_NAME_MAX_LEN];
- struct ctx_list *next;
-} *my_ctx_list;
+ xid_t xid;
+ int process_count;
+ int VmSize_total;
+ int VmRSS_total;
+ long start_time_oldest;
+ long stime_total, utime_total;
+};
struct process_info
{
long start_time; // start time of process -- seconds since 1-1-70
long stime, utime; // kernel & user-mode CPU time accumulated by process
long cstime, cutime; // cumulative time of process and reaped children
- int s_context;
+ xid_t s_context;
};
-char *process_name;
-
struct ArgInfo {
enum { tpUNSET, tpCTX, tpPID } type;
xid_t ctx;
return secs*100 + msecs;
}
-// insert a new record to the list
-static struct ctx_list *
-insert_ctx(int ctx, struct ctx_list *next)
-{
- struct ctx_list *new;
-
- new = (struct ctx_list *)malloc(sizeof(struct ctx_list));
- new->ctx = ctx;
- new->process_count = 0;
- new->VmSize_total = 0;
- new->VmRSS_total = 0;
- new->utime_total = 0;
- new->stime_total = 0;
- new->start_time_oldest = 0;
- new->next = next;
- new->name[0] = '\0';
-
- return new;
-}
-
-// compute the process info into the list
-static void
-add_ctx(struct ctx_list *list, struct process_info *process)
+static int
+cmpData(void const *xid_v, void const *map_v)
{
- list->process_count ++;
- list->VmSize_total += process->VmSize;
- list->VmRSS_total += process->VmRSS;
- list->utime_total += process->utime + process->cutime;
- list->stime_total += process->stime + process->cstime;
-
- if (list->start_time_oldest == 0) // first entry
- list->start_time_oldest = process->start_time;
- else
- if (list->start_time_oldest > process->start_time)
- list->start_time_oldest = process->start_time;
-}
+ xid_t const * const xid = xid_v;
+ struct XidData const * const map = map_v;
+ int res = *xid - map->xid;
-// increment the count number in the ctx record using ctx number
-static void
-count_ctx(struct ctx_list *list, struct process_info *process)
-{
- struct ctx_list *prev = list;
-
- if (process == NULL) return;
-
- // search
- while(list != NULL)
- {
- // find
- if (list->ctx == process->s_context)
- {
- add_ctx(list, process);
- return;
- }
- // insert between
- if (list->ctx > process->s_context)
- {
- prev->next = insert_ctx(process->s_context, list);
- add_ctx(prev->next, process);
- return;
- }
- // ++
- prev = list;
- list = list->next;
- }
- // add at the end
- prev->next = insert_ctx(process->s_context, NULL);
- add_ctx(prev->next, process);
+ return res;
}
-// free mem
static void
-free_ctx(struct ctx_list *list)
+registerXid(struct Vector *vec, struct process_info *process)
{
- struct ctx_list *prev;
+ struct XidData *res;
+
+ res = Vector_search(vec, &process->s_context, cmpData);
+ if (res==0) {
+ res = Vector_insert(vec, &process->s_context, cmpData);
+ res->xid = process->s_context;
+ res->process_count = 0;
+ res->VmSize_total = 0;
+ res->VmRSS_total = 0;
+ res->utime_total = 0;
+ res->stime_total = 0;
+ res->start_time_oldest = 0;
+ }
- for(;list != NULL; list = prev)
- {
- prev = list->next;
- free(list);
- }
+ ++res->process_count;
+ res->VmSize_total += process->VmSize;
+ res->VmRSS_total += process->VmRSS;
+ res->utime_total += process->utime + process->cutime;
+ res->stime_total += process->stime + process->cstime;
+
+ if (res->start_time_oldest == 0) // first entry
+ res->start_time_oldest = process->start_time;
+ else
+ if (res->start_time_oldest > process->start_time)
+ res->start_time_oldest = process->start_time;
}
-
// open the process's status file to get the ctx number, and other stat
struct process_info *get_process_info(char *pid)
{
- int fd;
- char buffer[1024];
- char *p;
- size_t idx, l=strlen(pid);
- static struct process_info process;
+ int fd;
+ char buffer[1024];
+ char *p;
+ size_t idx, l=strlen(pid);
+ static struct process_info process;
- process.s_context = vc_X_getctx(atoi(pid));
+#if 1
+ process.s_context = vc_get_task_xid(atoi(pid));
+#else
+# warning Compiling in debug-code
+ process.s_context = random()%6;
+#endif
+ if (process.s_context==VC_NOCTX) {
+ int err=errno;
+ WRITE_MSG(2, "vc_get_task_xid(");
+ WRITE_STR(2, pid);
+ WRITE_MSG(2, "): ");
+ WRITE_STR(2, strerror(err));
+ WRITE_MSG(2, "\n");
+ }
memcpy(buffer, "/proc/", 6); idx = 6;
memcpy(buffer+idx, pid, l); idx += l;
return &process;
}
-
-
static size_t
fillUintZero(char *buf, unsigned long val, size_t cnt)
{
memcpy(buf+10-(ptr-tmp), tmp, ptr-tmp);
}
-void showContexts(struct ctx_list *list)
+static void
+showContexts(struct Vector *vec)
{
uint64_t uptime = getUptime();
+ struct XidData const * ptr = Vector_begin_const(vec);
+ struct XidData const * const end_ptr = Vector_end_const(vec);
+
WRITE_MSG(1, "CTX PROC VSZ RSS userTIME sysTIME UPTIME NAME\n");
- while (list!=0) {
- char buf[512];
- char tmp[32];
+ for (; ptr<end_ptr; ++ptr) {
+ char buf[sizeof(xid_t)*3 + 512];
+ char tmp[sizeof(int)*3 + 2];
size_t l;
memset(buf, ' ', sizeof(buf));
- l = utilvserver_fmt_ulong(buf, list->ctx);
- l = utilvserver_fmt_ulong(tmp, list->process_count);
+ l = utilvserver_fmt_long(buf, ptr->xid);
+ l = utilvserver_fmt_long(tmp, ptr->process_count);
memcpy(buf+10-l, tmp, l);
- shortenMem (buf+10, list->VmSize_total);
- shortenMem (buf+17, list->VmRSS_total);
- shortenTime(buf+24, list->utime_total);
- shortenTime(buf+34, list->stime_total);
- shortenTime(buf+44, uptime - list->start_time_oldest);
+ shortenMem (buf+10, ptr->VmSize_total);
+ shortenMem (buf+17, ptr->VmRSS_total);
+ shortenTime(buf+24, ptr->utime_total);
+ shortenTime(buf+34, ptr->stime_total);
+ shortenTime(buf+44, uptime - ptr->start_time_oldest);
- switch (list->ctx) {
+ switch (ptr->xid) {
case 0 : strncpy(buf+55, "root server", 20); break;
case 1 : strncpy(buf+55, "monitoring server", 20); break;
default : {
- char * name = 0;
- char * cfgpath = 0;
+ char * name = 0;
+ char * cfgpath = 0;
vcCfgStyle cfgstyle = vcCFG_AUTO;
- if ((cfgpath = vc_getVserverByCtx(list->ctx, &cfgstyle, 0))!=0 &&
+ if ((cfgpath = vc_getVserverByCtx(ptr->xid, &cfgstyle, 0))!=0 &&
(name = vc_getVserverName(cfgpath, cfgstyle))!=0)
strncpy(buf+55, name, 20);
free(name);
write(1, buf, 80);
write(1, "\n", 1);
-
- list = list->next;
}
}
int main(int argc, char **argv)
{
- DIR *proc_dir;
- struct dirent *dir_entry;
- pid_t my_pid;
-
- // for error msg
- process_name = argv[0];
+ DIR * proc_dir;
+ struct dirent* dir_entry;
+ pid_t my_pid;
+ struct Vector xid_data;
if (argc==2) {
if (strcmp(argv[1], "--help") ==0) showHelp(1, argv[0], 0);
#if 1
// try to switch in context 1
- if (vc_new_s_context(1,0, 0) < 0)
- {
- perror("vc_new_s_context(#1,...)");
- return EXIT_FAILURE;
- }
+ if (vc_get_task_xid(0)!=1)
+ Evc_new_s_context(1, 0,0);
+#else
+# warning Compiling in debug-code
#endif
-
- // create the fist...
- my_ctx_list = insert_ctx(0, NULL);
- // init with the default name for the context 0
- strncpy(my_ctx_list->name, "root server", CTX_NAME_MAX_LEN);
-
- // open the /proc dir
- if ((proc_dir = opendir(PROC_DIR_NAME)) == NULL) {
- perror("opendir()");
- return EXIT_FAILURE;
- }
-
- chdir(PROC_DIR_NAME);
+
+ Vector_init(&xid_data, sizeof(struct XidData));
+
+ Echdir(PROC_DIR_NAME);
+ proc_dir = Eopendir(".");
while ((dir_entry = readdir(proc_dir)) != NULL)
{
// select only process file
continue;
if (atoi(dir_entry->d_name) != my_pid)
- count_ctx(my_ctx_list, get_process_info(dir_entry->d_name));
-
+ registerXid(&xid_data, get_process_info(dir_entry->d_name));
}
closedir(proc_dir);
// output the ctx_list
- showContexts(my_ctx_list);
-
- // free the ctx_list
- free_ctx(my_ctx_list);
+ showContexts(&xid_data);
+#ifndef NDEBUG
+ Vector_free(&xid_data);
+#endif
+
return 0;
}