/* * Remove the job indexed by ikey from the jobs queue. * Removes job structure and flags removal to underlying runq class. * No further work should be carried out for the job identified by key * but runq may take a while to catch up if there are any proccesses * involved. * Returns 1=success, 0=error. */ int job_rm(int ikey /* job key */) { struct job_work *w; /* Find job details */ if ((w = itree_find(job_tab, ikey)) == ITREE_NOVAL) { elog_printf(ERROR, "job not found (id %d)", ikey); return 0; } /* Debug: Notify the removal from the job list */ elog_printf(DEBUG, "remove job %s", w->runarg->key); /* Remove runq work instruction */ if (!runq_rm(w->runq)) { elog_printf(DEBUG, "job %s can't remove runq (id %d)", w->runarg->key, w->runq); return 0; } itree_rm(job_tab); /* Remove job record */ /* Free job storage excluding w->runarg which was reparented by runq */ nfree(w->origin); nfree(w); return(1); }
/* get the name of a user by uid, caching results in the ITREE */ char *plinps_getuser(int uid, ITREE *uidtoname) { char *name; struct passwd *pwent; /* return name if in table */ name = itree_find(uidtoname, uid); if (name != ITREE_NOVAL) return name; /* fetch pw entry and load name into table */ pwent = getpwuid(uid); if (pwent) itree_add(uidtoname, uid, xnstrdup(pwent->pw_name)); else itree_add(uidtoname, uid, xnstrdup("unknown")); return itree_find(uidtoname, uid); }
uint8_t topology_distance(uint32_t ip1,uint32_t ip2) { uint32_t rid1,rid2; if (ip1==ip2) { return 0; } // rid1 = hash_find(ip1); // rid2 = hash_find(ip2); rid1 = itree_find(racktree,ip1); rid2 = itree_find(racktree,ip2); // rid1^=rid2; // rid2=0; // while(rid1) { // if (rid1&1) { // rid2++; // } // rid1>>=1; // } // return rid2; return (rid1==rid2)?1:2; }
/* * Linux specific routines */ void pmacnet_collect(TABLE tab) { char *data; ITREE *lines; /* open and process the network stats file */ data = probe_readfile("/proc/net/dev"); if (data) { /*elog_printf(DEBUG, "Read from /proc/net/dev: %s", data);*/ util_scantext(data, ": |", UTIL_MULTISEP, &lines); /* scan */ itree_find(lines, 2); /* data starts at 3rd line */ while(!itree_isbeyondend(lines)) { table_addemptyrow(tab); pmacnet_col_netdev(tab, itree_get(lines) ); itree_next(lines); } /* clear up */ util_scanfree(lines); table_freeondestroy(tab, data); } }
/* takes data from /procs's status structure into the table */ void plinps_col_status(TABLE tab, char *ps, ITREE *uidtoname) { ITREE *lines, *cols; char *key, *val; int seen_vmdata=0, seen_vmlib=0, seen_vmexe=0; /* Format is similar to:- * Name: bash * State: R (running) * SleepAVG: 100% * Tgid: 4916 * Pid: 4916 * PPid: 4903 * TracerPid: 0 * Uid: 501 501 501 501 * Gid: 501 501 501 501 * FDSize: 256 * Groups: 501 * VmSize: 3120 kB * VmLck: 0 kB * VmRSS: 1852 kB * VmData: 952 kB * VmStk: 24 kB * VmExe: 580 kB * VmLib: 1264 kB * Threads: 1 * SigPnd: 0000000000000000 * ShdPnd: 0000000000000000 * SigBlk: 0000000000010002 * SigIgn: 0000000000384004 * SigCgt: 000000004b813efb * CapInh: 0000000000000000 * CapPrm: 0000000000000000 * CapEff: 0000000000000000 */ util_scantext(ps, " \t:", UTIL_MULTISEP, &lines); itree_traverse(lines) { cols = itree_get(lines); key = itree_find(cols, 0); if (key == ITREE_NOVAL) continue; switch(key[0]) { case 'N': /* Name */ break; case 'S': /* State, SleepSVG, Sig* */ break; case 'T': /* Tgid, TracerPid, Threads */ break; case 'P': /* Pid, PPid */ break; case 'U': /* Uid */ if (strcmp(key, "Uid") == 0) { /* real uid */ itree_next(cols); val = itree_get(cols); table_replacecurrentcell(tab, "uid", val); table_replacecurrentcell(tab, "pwname", plinps_getuser(strtol(val, NULL, 10), uidtoname)); /* effective uid */ itree_next(cols); val = itree_get(cols); table_replacecurrentcell(tab, "euid", val); table_replacecurrentcell(tab, "epwname", plinps_getuser(strtol(val, NULL, 10), uidtoname)); #if 0 itree_next(cols); val = itree_get(cols); /* suid - saved user id */ itree_next(cols); val = itree_get(cols); /* fuid - fs user id */ #endif } break; case 'G': /* Gid, Groups */ if (strcmp(key, "Gid") == 0) { /* real gid */ itree_next(cols); val = itree_get(cols); table_replacecurrentcell(tab, "gid", val); /* effective gid */ itree_next(cols); val = itree_get(cols); table_replacecurrentcell(tab, "egid", val); #if 0 itree_next(cols); val = itree_get(cols); /* sgid - saved group id */ itree_next(cols); val = itree_get(cols); /* fgid - fs group id */ #endif } break; case 'F': /* FDSize */ break; case 'V': /* Vm* */ if (strcmp(key, "VmData") == 0) { itree_next(cols); val = itree_get(cols); table_replacecurrentcell(tab, "data_size", val); seen_vmdata++; } if (strcmp(key, "VmLib") == 0) { itree_next(cols); val = itree_get(cols); table_replacecurrentcell(tab, "library", val); seen_vmlib++; } if (strcmp(key, "VmExe") == 0) { itree_next(cols); val = itree_get(cols); table_replacecurrentcell(tab, "text_size", val); seen_vmexe++; } break; case 'C': /* Cap* */ break; default: break; } } util_scanfree(lines); if (!seen_vmdata) table_replacecurrentcell_alloc(tab, "data_size", "0"); if (!seen_vmlib) table_replacecurrentcell_alloc(tab, "library", "0"); if (!seen_vmexe) table_replacecurrentcell_alloc(tab, "text_size", "0"); }
/* * Read in job definitions from the pseudo-url and add them to the * job class. If there is a problem with a job definition, it will not * be added to the job class, but other jobs will continue to be processed. * * File format: one line per job. magic string of 'job 1' at top * Fields/columns match the job_add() spec and are: * 1. start time (seconds) * 2. interval (currently seconds, but ought to have weekly or monthly based * intervals as well) * 3. phase (int; job order at each scheduled point) * 4. count (int; how many times to run; 0=indefinately) * 5. key (unique job id) * 6. origin (char *; no spaces) * 7. result (pseudo-url; where to send results) * 8. errors (pseudo-url; where to send errors) * 9. keep (number of results to keep in timestore or tablestore) * 10.method (char *; string representation of method) * 11.command (char *; command for method to run) * * The result url, error url and command are parsed for tokens of the * form %x, where x is a single letter. These are expanded into context * specific strings. Currently, %h is hostname and %j is jobname. See * route_expand() for more details. * * Returns the number of jobs added, or -1 for a major problem */ int job_loadroute(char *purl /* p-url location of file */ ) { long start, interval, phase, count, keep; char *key, *origin, *result, *error, *method, *command; char *endint; ITREE *jobdefs, *job; int r, njobdefs, jobsadded = 0; char key_t[60], result_t[256], error_t[256], command_t[1024]; /* read jobs into parse structure */ njobdefs = util_parseroute(purl, " \t", "job 1", &jobdefs); if (njobdefs < 1) return -1; util_parsedump(jobdefs); itree_traverse(jobdefs) { job = itree_get(jobdefs); /* check the size of each row */ if (itree_n(job) != 11) { elog_startprintf(ERROR, "%s row %d has %d fields, want 11 (", purl, itree_getkey(jobdefs)+1, itree_n(job) ); itree_traverse(job) elog_contprintf(ERROR, "%s ", (char *) itree_get(job)); elog_endprintf(ERROR, ")"); continue; } /* * validate each column * we dont need to strdup() any space because job_add() will * do that for itself */ /* column 1: start time */ itree_find(job, 0); start = strtol( itree_get(job), &endint, 10 ); if (start == LONG_MIN || start == LONG_MAX || itree_get(job) == endint) { elog_printf(ERROR, "%s row %d start time (column 1) is " "incorrect: '%s'; skipping", purl, itree_getkey(jobdefs), itree_get(job)); continue; } /* column 2: interval */ itree_find(job, 1); interval = strtol( itree_get(job), &endint, 10 ); if (interval == LONG_MIN || interval == LONG_MAX || itree_get(job) == endint) { elog_printf(ERROR, "%s row %d interval (column 2) is " "incorrect: '%s'; skipping", purl, itree_getkey(jobdefs), itree_get(job)); continue; } /* column 3: phase */ itree_find(job, 2); phase = strtol( itree_get(job), &endint, 10 ); if (phase == LONG_MIN || phase == LONG_MAX || itree_get(job) == endint) { elog_printf(ERROR, "%s row %d phase (column 3) is incorrect: " "'%s'; skipping", purl, itree_getkey(jobdefs), itree_get(job)); continue; } /* column 4: count */ itree_find(job, 3); count = strtol( itree_get(job), &endint, 10 ); if (count == LONG_MIN || count == LONG_MAX || itree_get(job) == endint) { elog_printf(ERROR, "%s row %d count (column 4) is incorrect: " "'%s'; skipping", purl, itree_getkey(jobdefs), itree_get(job)); continue; } /* column 5: key */ itree_find(job, 4); key = itree_get(job); if (route_expand(key_t, key, key, interval) != -1) key = key_t; /* column 6: origin */ itree_find(job, 5); origin = itree_get(job); /* column 7: result */ itree_find(job, 6); result = itree_get(job); if (route_expand(result_t, result, key, interval) != -1) result = result_t; /* column 8: error */ itree_find(job, 7); error = itree_get(job); if (route_expand(error_t, error, key, interval) != -1) error = error_t; /* column 9: keep */ itree_find(job, 8); keep = strtol( itree_get(job), &endint, 10 ); if (keep == LONG_MIN || keep == LONG_MAX || itree_get(job) == endint) { elog_printf(ERROR, "%s row %d keep (column 9) is incorrect: " "'%s'; skipping", purl, itree_getkey(jobdefs), itree_get(job)); continue; } /* column 10: method */ itree_find(job, 9); method = itree_get(job); /* column 11: command */ itree_find(job, 10); command = itree_get(job); if (route_expand(command_t, command, key, interval) != -1) command = command_t; elog_printf(DEBUG, "%s row %d read: start=%ld interval=%ld phase=%ld " "count=%ld key=%s origin=%s result=%s error=%s keep=%ld " "method=%s command=%s", purl, itree_getkey(jobdefs), start, interval, phase, count, key, origin, result, error, keep, method, command); if (meth_check(method)) { elog_printf(ERROR, "%s row %d method %s not loaded; skipping", purl, itree_getkey(jobdefs), method); continue; } /* insert into job class */ r = job_add(start, interval, phase, count, key, origin, result, error, keep, method, command); if (r == -1) elog_printf(ERROR, "%s row %d unable to add job; skipping", purl, itree_getkey(jobdefs)); else jobsadded++; } util_freeparse(jobdefs); return jobsadded; }
/* * Calculate the major and minor x-axis points of a time line, given the * line size and viewing scale. * Dispdiff is a representation of the displayed scale and should be * ( <upper time> - <lower time> ), giving the number seconds being * displayed at once. * Min and max times have an offset added as set by timeline_setoffset(). * Results are returned in an ITREE list, with the key being time_t * and the value being a pointer to a struct timeline_tick. * The value node indicates the type of tick it is and the text label * associated with it. * Returns NULL for an error, such as being impossible to work out. */ ITREE *timeline_ocalc(time_t min, /* start of the timeline */ time_t max, /* end of timeline */ time_t dispdiff /* viewing area for scale */ ) { int tickindex; /* index to applicable tick point */ ITREE *results; /* returned results */ time_t t; /* working time */ struct tm t_tm; /* working time breakdown */ struct tm *t_tmp; /* returned time breakdown pointer */ struct timeline_tick *tick; /* tick details */ char label[TIMELINE_SHORTSTR]; /* working label text */ /* we must have at least 3 seconds to work sensibly */ if (min +3 >= max || dispdiff < 3) return NULL; results = itree_create(); /* find which tick is applicable */ for (tickindex = 0; timeline_tickpoints[ tickindex ].threshold; tickindex++) if (dispdiff <= timeline_tickpoints[ tickindex ].threshold) break; /* start point (non-tick) */ t = min + timeline_offset; t_tmp = localtime(&t); strftime(label, TIMELINE_SHORTSTR, "%d%b%y", t_tmp); /* store non-tick! as a result */ tick = nmalloc(sizeof(struct timeline_tick)); tick->type = TIMELINE_NONE; tick->label = xnstrdup(label); tick->point = min; itree_add(results, min, tick); /* run off major ticks */ t = min + timeline_offset; while (1) { /* add major tick increment */ t += timeline_tickpoints[ tickindex ].major; t_tmp = localtime(&t); memcpy(&t_tm, t_tmp, sizeof(struct tm)); /* round down */ timeline_rounddown(&t_tm, timeline_tickpoints[ tickindex ].base); t = mktime(&t_tm); /* loop check */ if (t >= max + timeline_offset) break; /* create label text */ switch (timeline_tickpoints[ tickindex ].base) { case NOUNIT: strftime(label, TIMELINE_SHORTSTR, "??", &t_tm); break; case SECS: strftime(label, TIMELINE_SHORTSTR, "%H:%M:%S", &t_tm); break; case MINS: strftime(label, TIMELINE_SHORTSTR, "%H:%M", &t_tm); break; case HOURS: strftime(label, TIMELINE_SHORTSTR, "%H:00", &t_tm); break; case WEEKDAYS: strftime(label, TIMELINE_SHORTSTR, "%a", &t_tm); break; case DAYS: strftime(label, TIMELINE_SHORTSTR, "%d%b", &t_tm); break; case MDAYS: strftime(label, TIMELINE_SHORTSTR, "%d", &t_tm); break; case MONTHS: strftime(label, TIMELINE_SHORTSTR, "%b", &t_tm); break; case YEARS: strftime(label, TIMELINE_SHORTSTR, "%Y", &t_tm); break; } /* store tick as a result */ tick = nmalloc(sizeof(struct timeline_tick)); tick->type = TIMELINE_MAJOR; tick->label = xnstrdup(label); tick->point = t - timeline_offset; itree_add(results, t - timeline_offset, tick); } /* run off minor ticks */ t = min + timeline_offset; while (1) { /* add maior tick increment */ t += timeline_tickpoints[ tickindex ].minor; #if 0 /* suggest that minor ticks do not need the rounding treatment */ t_tmp = localtime(&t); memcpy(&t_tm, t_tmp, sizeof(struct tm)); /* round down */ timeline_rounddown(&t_tm, timeline_tickpoints[ tickindex ].base); t = mktime(&t_tm); printf("%d\n", t); #endif /* loop check */ if (t >= max + timeline_offset) break; /* store tick as a result if there is not a major tick already */ if (itree_find(results, t) == ITREE_NOVAL) { tick = nmalloc(sizeof(struct timeline_tick)); tick->type = TIMELINE_MINOR; tick->label = NULL; tick->point = t - timeline_offset; itree_add(results, t - timeline_offset, tick); } } /* max point (non-tick) */ t = max + timeline_offset; t_tmp = localtime(&t); strftime(label, TIMELINE_SHORTSTR, "%d%b%y", t_tmp); /* store non-tick! as a result */ tick = nmalloc(sizeof(struct timeline_tick)); tick->type = TIMELINE_NONE; tick->label = xnstrdup(label); tick->point = max; itree_add(results, max, tick); return results; }
/* * Calculate the major and minor x-axis points of a time line, given the * line size and viewing scale. * Dispdiff is a representation of the displayed scale and should be * ( <upper time> - <lower time> ), giving the number seconds being * displayed at once. * Min and max times have an offset added as set by timeline_setoffset(). * Results are returned in an ITREE list, with the key being time_t * and the value being a pointer to a struct timeline_tick. * The value node indicates the type of tick it is and the text label * associated with it. * Returns NULL for an error, such as being impossible to work out. */ ITREE *timeline_calc(time_t min, /* start of the timeline */ time_t max, /* end of timeline */ time_t dispdiff, /* viewing area for scale */ int maxchars /* max number of chars possible */) { int diff; /* diff betwix min+max */ int maxlabels; /* max number of labels poss */ int tickindex; /* index to applicable tick point */ ITREE *results; /* returned results */ time_t t; /* working time */ struct tm t_tm; /* working time breakdown */ struct timeline_tick *tick; /* tick details */ char label[TIMELINE_SHORTSTR]; /* working label text */ #if 0 fprintf(stderr, "min %ld (%s), max %ld (%s), diff %ld, maxchars %d\n", min, util_decdatetime(min+timeline_offset), max, util_sdecdatetime(max+timeline_offset), dispdiff, maxchars); #endif /* we must have at least 3 seconds to work sensibly */ diff = max - min; if (min +3 >= max || diff < 3) return NULL; /* work out the maximum number of labels possible, if the widest * is 8 chars + 1 for the major tick + 1 space */ maxlabels = maxchars / (1+8+1); results = itree_create(); /* find which tick is applicable from the table */ for (tickindex = 0; timeline_tickpoints[ tickindex ].threshold; tickindex++) if (dispdiff <= timeline_tickpoints[ tickindex ].threshold) break; #if 0 fprintf(stderr, "tkidx %d, thresh %d, base %d, maj %d, min %d, desc %s\n", tickindex, timeline_tickpoints[ tickindex ].threshold, timeline_tickpoints[ tickindex ].base, timeline_tickpoints[ tickindex ].major, timeline_tickpoints[ tickindex ].minor, timeline_tickpoints[ tickindex ].description); #endif /* Start point should be the DATE of the min as a non-tick. Store it */ t = min + timeline_offset; localtime_r(&t, &t_tm); strftime(label, TIMELINE_SHORTSTR, "%d%b%y", &t_tm); tick = nmalloc(sizeof(struct timeline_tick)); tick->type = TIMELINE_NONE; tick->label = xnstrdup(label); tick->point = min; tick->ptime = t; itree_add(results, tick->point, tick); #if 0 fprintf(stderr, " point %ld (%s), type %d, label %s\n", tick->point, util_decdatetime(t), tick->type, tick->label); #endif /* Min and max are the visible limits of the chart. * The counting, however, needs to start from the greatest major * point lower than the min */ t -= timeline_tickpoints[ tickindex ].major; /* establish the first rounded time before looping */ timeline_rounddown(&t_tm, timeline_tickpoints[ tickindex ].base); t = mktime(&t_tm); /* run off major ticks */ while (t < max + timeline_offset) { /* add major tick increment */ t += timeline_tickpoints[ tickindex ].major; localtime_r(&t, &t_tm); /* create label text */ switch (timeline_tickpoints[ tickindex ].base) { case NOUNIT: strftime(label, TIMELINE_SHORTSTR, "??", &t_tm); break; case SECS: strftime(label, TIMELINE_SHORTSTR, "%H:%M:%S", &t_tm); break; case MINS: strftime(label, TIMELINE_SHORTSTR, "%H:%M", &t_tm); break; case HOURS: strftime(label, TIMELINE_SHORTSTR, "%H:00", &t_tm); break; case WEEKDAYS: strftime(label, TIMELINE_SHORTSTR, "%a", &t_tm); break; case DAYS: strftime(label, TIMELINE_SHORTSTR, "%d%b", &t_tm); break; case MDAYS: strftime(label, TIMELINE_SHORTSTR, "%d", &t_tm); break; case MONTHS: strftime(label, TIMELINE_SHORTSTR, "%b", &t_tm); break; case YEARS: strftime(label, TIMELINE_SHORTSTR, "%Y", &t_tm); break; } /* store tick as a result */ tick = nmalloc(sizeof(struct timeline_tick)); tick->type = TIMELINE_MAJOR; tick->label = xnstrdup(label); tick->point = t - timeline_offset; tick->ptime = t; itree_add(results, tick->point, tick); /* really need an itree? */ #if 0 fprintf(stderr, " point %ld (%s), type %d, label %s\n", tick->point, util_decdatetime(t), tick->type, tick->label); #endif } #if 0 /* DISABLE MINOR TICKS AS GTK_DATABOX DOES NOT SUPPORT IT DIRECTLY */ /* run off minor ticks */ t = min + timeline_offset; /* As major points, start counting from the greatest minor * point lower than the min */ t -= timeline_tickpoints[ tickindex ].minor; localtime_r(&t, &t_tm); /* establish the first rounded time before looping */ timeline_rounddown(&t_tm, timeline_tickpoints[ tickindex ].base); t = mktime(&t_tm); while (t < max + timeline_offset) { /* add minor tick increment */ t += timeline_tickpoints[ tickindex ].minor; localtime_r(&t, &t_tm); /* store tick as a result if there is not a major tick already */ if (itree_find(results, t) == ITREE_NOVAL) { tick = nmalloc(sizeof(struct timeline_tick)); tick->type = TIMELINE_MINOR; tick->label = NULL; tick->point = t - timeline_offset; tick->ptime = t; itree_add(results, tick->point, tick); #if 0 fprintf(stderr, " point %ld (%s), type %d, label %s\n", tick->point, util_decdatetime(t), tick->type, tick->label); #endif } } #endif /* max point (non-tick) */ t = max + timeline_offset; localtime_r(&t, &t_tm); strftime(label, TIMELINE_SHORTSTR, "%d%b%y", &t_tm); /* store non-tick! as a result */ tick = nmalloc(sizeof(struct timeline_tick)); tick->type = TIMELINE_NONE; tick->label = xnstrdup(label); tick->point = max; tick->ptime = t; itree_add(results, max, tick); #if 0 fprintf(stderr, " point %ld (%s), type %d, label %s\n", tick->point, util_decdatetime(t), tick->type, tick->label); #endif return results; }