static double eval_expr(const char *buf, int *pos) /* expr = term+expr | term-expr | term */ { double rv = 0.0, lhs, rhs; Token tok; DB(printf("-- eval_expr(\"%s\", &pos=%p pos=%d)\n", buf+*pos, pos, *pos)); lhs = eval_term(buf, pos); if(G_eval_error) return rv; DB(printf("-- expr lhs=%f\n", lhs)); tok = pull_token(buf, pos); if(G_eval_error) return rv; DB(printf("-- expr token type '%c' = ", tok.type)); switch(tok.type) { case '\0': DB(printf("END OF BUFFER\n")); rv = lhs; break; case '+': /* addition */ rhs = eval_expr(buf, pos); DB(printf("%f+%f", lhs, rhs)); rv = lhs+rhs; DB(printf("=%f\n", rv)); break; case '-': /* subtraction */ rhs = eval_expr(buf, pos); DB(printf("%f-%f", lhs, rhs)); rv = lhs-rhs; DB(printf("=%f\n", rv)); break; case ')': /* end of group */ DB(printf("end group")); push_token(tok); rv = lhs; DB(printf(" (rv=%f)\n", rv)); break; case ',': /* argument delimiter */ DB(printf("delimiter")); push_token(tok); rv = lhs; DB(printf(" (rv=%f)\n", rv)); break; default: DB(printf("invalid expr token\n")); G_eval_error = EVAL_SYNTAX_ERROR; rv = lhs; } DB(printf("-- expr rv=%f\n", rv)); return rv; }
Value eval(const Tree& tree, const Params& params, void* p, Cost* limit) { switch (tree.expr_id().type) { case Expr::Term: { return eval_term(tree.expr_id().index, params, p, limit); } case Expr::Func: { Args args; for (const Tree& child : tree.children()) args.push_back(eval(child, params, p, limit)); return eval_func(tree.expr_id().index, args, p, limit); } case Expr::Select: { unsigned branch = eval_select(tree.expr_id().index, params, p, limit); assert(branch < tree.children().size()); return eval(tree.children()[branch], params, p, limit); } case Expr::Invalid: throw std::logic_error("Invalid expression"); } assert(false); }
static double eval_term(const char *buf, int *pos) /* term = fact*term | fact/term | fact */ { double rv = 0.0, lhs, rhs; Token tok; DB(printf("-- eval_term(\"%s\", &pos=%p pos=%d)\n", buf+*pos, pos, *pos)); lhs = eval_fact(buf, pos); if(G_eval_error) return rv; DB(printf("-- term lhs=%f\n", lhs)); tok = pull_token(buf, pos); if(G_eval_error) return rv; DB(printf("-- term token type '%c' = ", tok.type)); switch(tok.type) { case '\0': DB(printf("END OF BUFFER\n")); rv = lhs; break; case '*': /* multiplication */ rhs = eval_term(buf, pos); DB(printf("%f*%f", lhs, rhs)); rv = lhs*rhs; DB(printf("=%f\n", rv)); break; case '/': /* division */ rhs = eval_term(buf, pos); DB(printf("%f/%f", lhs, rhs)); if(rhs == 0.0) { DB(printf(" DIVISION BY ZERO\n")); G_eval_error = EVAL_DIVIDE_BY_ZERO; }else { rv = lhs/rhs; DB(printf("=%f\n", rv)); } break; case '\\': /* modulo division */ rhs = eval_term(buf, pos); DB(printf("%f%%%f", lhs, rhs)); if(rhs == 0.0) { DB(printf(" DIVISION BY ZERO\n")); G_eval_error = EVAL_DIVIDE_BY_ZERO; }else { rv = fmod(lhs, rhs); DB(printf("=%f\n", rv)); } break; default: DB(printf("PUSHBACK\n")); push_token(tok); rv = lhs; } DB(printf("-- term rv=%f\n", rv)); return rv; }
static void eval_cpu_rules(void) { double diffs[CPUSTATS], diffs_total, percent_factor; char *procinfo_current, *procinfo_prev; int cpu, nr_cpus, on_off; nr_cpus = get_numcpus(); procinfo_current = cpustat + history_current * cpustat_size; procinfo_prev = cpustat + history_prev * cpustat_size; diffs[0] = get_proc_value(procinfo_current, "user", ' ') - get_proc_value(procinfo_prev, "user", ' '); diffs[1] = get_proc_value(procinfo_current, "nice", ' ') - get_proc_value(procinfo_prev, "nice", ' '); diffs[2] = get_proc_value(procinfo_current, "system", ' ') - get_proc_value(procinfo_prev, "system", ' '); diffs[3] = get_proc_value(procinfo_current, "idle", ' ') - get_proc_value(procinfo_prev, "idle", ' '); diffs[4] = get_proc_value(procinfo_current, "iowait", ' ') - get_proc_value(procinfo_prev, "iowait", ' '); diffs[5] = get_proc_value(procinfo_current, "irq", ' ') - get_proc_value(procinfo_prev, "irq", ' '); diffs[6] = get_proc_value(procinfo_current, "softirq", ' ') - get_proc_value(procinfo_prev, "softirq", ' '); diffs[7] = get_proc_value(procinfo_current, "steal", ' ') - get_proc_value(procinfo_prev, "steal", ' '); diffs[8] = get_proc_value(procinfo_current, "guest", ' ') - get_proc_value(procinfo_prev, "guest", ' '); diffs[9] = get_proc_value(procinfo_current, "guest_nice", ' ') - get_proc_value(procinfo_prev, "guest_nice", ' '); diffs_total = get_proc_value(procinfo_current, "total_ticks", ' ') - get_proc_value(procinfo_prev, "total_ticks", ' '); if (diffs_total == 0) diffs_total = 1; symbols.loadavg = get_proc_value(procinfo_current, "loadavg", ' '); symbols.runnable_proc = get_proc_value(procinfo_current, "runnable_proc", ' '); symbols.onumcpus = get_proc_value(procinfo_current, "onumcpus", ' '); percent_factor = 100 * symbols.onumcpus; symbols.user = (diffs[0] / diffs_total) * percent_factor; symbols.nice = (diffs[1] / diffs_total) * percent_factor; symbols.system = (diffs[2] / diffs_total) * percent_factor; symbols.idle = (diffs[3] / diffs_total) * percent_factor; symbols.iowait = (diffs[4] / diffs_total) * percent_factor; symbols.irq = (diffs[5] / diffs_total) * percent_factor; symbols.softirq = (diffs[6] / diffs_total) * percent_factor; symbols.steal = (diffs[7] / diffs_total) * percent_factor; symbols.guest = (diffs[8] / diffs_total) * percent_factor; symbols.guest_nice = (diffs[9] / diffs_total) * percent_factor; /* only use this for development and testing */ cpuplugd_debug("cpustat values:\n%s", cpustat + history_current * cpustat_size); if (debug && foreground == 1) { printf("-------------------- CPU --------------------\n"); printf("cpu_min: %ld\n", cfg.cpu_min); printf("cpu_max: %ld\n", cfg.cpu_max); printf("loadavg: %f \n", symbols.loadavg); printf("user percent = %f\n", symbols.user); printf("nice percent = %f\n", symbols.nice); printf("system percent = %f\n", symbols.system); printf("idle percent = %f\n", symbols.idle); printf("iowait percent = %f\n", symbols.iowait); printf("irq percent = %f\n", symbols.irq); printf("softirq percent = %f\n", symbols.softirq); printf("steal percent = %f\n", symbols.steal); printf("guest percent = %f\n", symbols.guest); printf("guest_nice percent = %f\n", symbols.guest_nice); printf("numcpus %d\n", nr_cpus); printf("runnable_proc: %d\n", (int) symbols.runnable_proc); printf("---------------------------------------------\n"); printf("onumcpus: %d\n", (int) symbols.onumcpus); printf("---------------------------------------------\n"); printf("hotplug: "); print_term(cfg.hotplug); printf("\n"); printf("hotunplug: "); print_term(cfg.hotunplug); printf("\n"); printf("---------------------------------------------\n"); } on_off = 0; /* Evaluate the hotplug rule */ if (eval_term(cfg.hotplug, &symbols)) on_off++; /* Evaluate the hotunplug rule only if hotplug did not match */ else if (eval_term(cfg.hotunplug, &symbols)) on_off--; if (on_off > 0) { /* check the cpu nr limit */ if (symbols.onumcpus + 1 > cfg.cpu_max) { /* cpu limit reached */ cpuplugd_debug("maximum cpu limit is reached\n"); return; } /* try to find a offline cpu */ for (cpu = 0; cpu < nr_cpus; cpu++) if (is_online(cpu) == 0 && cpu_is_configured(cpu) != 0) break; if (cpu < nr_cpus) { cpuplugd_debug("cpu with id %d is currently offline " "and will be enabled\n", cpu); if (hotplug(cpu) == -1) cpuplugd_debug("unable to find a cpu which " "can be enabled\n"); } else { /* * In case we tried to enable a cpu but this failed. * This is the case if a cpu is deconfigured */ cpuplugd_debug("unable to find a cpu which can " "be enabled\n"); } } else if (on_off < 0) { /* check cpu nr limit */ if (symbols.onumcpus <= cfg.cpu_min) { cpuplugd_debug("minimum cpu limit is reached\n"); return; } /* try to find a online cpu */ for (cpu = get_numcpus() - 1; cpu >= 0; cpu--) { if (is_online(cpu) != 0) break; } if (cpu > 0) { cpuplugd_debug("cpu with id %d is currently online " "and will be disabled\n", cpu); hotunplug(cpu); } } }
static void eval_mem_rules(double interval) { long cmmpages_size, cmm_inc, cmm_dec, cmm_new; double free_memory, swaprate, apcr; char *procinfo_current, *procinfo_prev; procinfo_current = meminfo + history_current * meminfo_size; free_memory = get_proc_value(procinfo_current, "MemFree", ':'); procinfo_current = vmstat + history_current * vmstat_size; procinfo_prev = vmstat + history_prev * vmstat_size; swaprate = (get_proc_value(procinfo_current, "pswpin", ' ') + get_proc_value(procinfo_current, "pswpout", ' ') - get_proc_value(procinfo_prev, "pswpin", ' ') - get_proc_value(procinfo_prev, "pswpout", ' ')) / interval; apcr = (get_proc_value(procinfo_current, "pgpgin", ' ') + get_proc_value(procinfo_current, "pgpgout", ' ') - get_proc_value(procinfo_prev, "pgpgin", ' ') - get_proc_value(procinfo_prev, "pgpgout", ' ')) / interval; cmmpages_size = get_cmmpages_size(); symbols.apcr = apcr; // apcr in 512 byte blocks / sec symbols.swaprate = swaprate; // swaprate in 4K pages / sec symbols.freemem = free_memory / 1024; // freemem in MB cmm_inc = eval_double(cfg.cmm_inc, &symbols); /* cmm_dec is optional */ if (cfg.cmm_dec) cmm_dec = eval_double(cfg.cmm_dec, &symbols); else cmm_dec = cmm_inc; /* only use this for development and testing */ if (debug && foreground == 1) { printf("------------------- Memory ------------------\n"); printf("cmm_min: %ld\n", cfg.cmm_min); printf("cmm_max: %ld\n", cfg.cmm_max); printf("swaprate: %f\n", symbols.swaprate); printf("apcr: %f\n", symbols.apcr); printf("cmm_inc: %ld = ", cmm_inc); print_term(cfg.cmm_inc); printf("\n"); printf("cmm_dec: %ld = ", cmm_dec); if (cfg.cmm_dec) print_term(cfg.cmm_dec); else print_term(cfg.cmm_inc); printf("\n"); printf("free memory: %f MB\n", symbols.freemem); printf("---------------------------------------------\n"); printf("cmm_pages: %ld\n", cmmpages_size); printf("---------------------------------------------\n"); printf("memplug: "); print_term(cfg.memplug); printf("\n"); printf("memunplug: "); print_term(cfg.memunplug); printf("\n"); printf("---------------------------------------------\n"); } cmm_new = cmmpages_size; /* Evaluate the memplug rule */ if (eval_term(cfg.memplug, &symbols)) { if (cmm_dec < 0) { cpuplugd_error("cmm_dec went negative (%ld), set it " "to 0.\n", cmm_dec); cmm_dec = 0; } cmm_new -= cmm_dec; /* Evaluate the memunplug rule only if memplug did not match */ } else if (eval_term(cfg.memunplug, &symbols)) { if (cmm_inc < 0) { cpuplugd_error("cmm_inc went negative (%ld), set it " "to 0.\n", cmm_inc); cmm_inc = 0; } cmm_new += cmm_inc; } if (cmm_new < cfg.cmm_min) { cpuplugd_debug("minimum memory limit is reached\n"); cmm_new = cfg.cmm_min; } if (cmm_new > cfg.cmm_max) { cpuplugd_debug("maximum memory limit is reached\n"); cmm_new = cfg.cmm_max; } if (cmm_new != cmmpages_size) set_cmm_pages(cmm_new); }