/** Do layout for the case where the end directions are opposite. * This can be either a straight line, a zig-zag, a rotated s-shape or * a spiral. * @param to Where to lay out to, coming from origo. * @param num_points Return value of how many points in the points array. * @param points The points in the layout. Free the array after use. The * passed in is ignored and overwritten, so should be NULL. * @returns The badness of this layout. */ static real autoroute_layout_opposite(Point *to, guint *num_points, Point **points) { Point *ps = NULL; if (to->y < -MIN_DIST) { *num_points = 4; ps = g_new0(Point, *num_points); if (fabs(to->x) < 0.00000001) { ps[2] = ps[3] = *to; *points = ps; return length_badness(fabs(to->y))+2*EXTRA_SEGMENT_BADNESS; } else { real mid = to->y/2; /* printf("Doing opposite layout: Three-way\n"); */ /* points[0] is 0,0 */ ps[1].y = mid; ps[2].x = to->x; ps[2].y = mid; ps[3] = *to; *points = ps; return 2*length_badness(fabs(mid))+2*EXTRA_SEGMENT_BADNESS; } } else if (fabs(to->x) > 2*MIN_DIST) { real mid = to->x/2; /* printf("Doing opposite layout: Doorhanger\n"); */ *num_points = 6; ps = g_new0(Point, *num_points); /* points[0] is 0,0 */ ps[1].y = -MIN_DIST; ps[2].x = mid; ps[2].y = -MIN_DIST; ps[3].x = mid; ps[3].y = to->y+MIN_DIST; ps[4].x = to->x; ps[4].y = to->y+MIN_DIST; ps[5] = *to; } else { real off = MIN_DIST*(to->x>0?-1.0:1.0); /* printf("Doing opposite layout: Overlap\n"); */ *num_points = 6; ps = g_new0(Point, *num_points); ps[1].y = -MIN_DIST; ps[2].x = off; ps[2].y = -MIN_DIST; ps[3].x = off; ps[3].y = to->y+MIN_DIST; ps[4].x = to->x; ps[4].y = to->y+MIN_DIST; ps[5] = *to; } *points = ps; return calculate_badness(ps, *num_points); }
/*! * \brief Parallel layout * * Lay out autorouting where start and end lines are parallel pointing the * same direction. This can either a simple up-right-down layout, or if the * to point is too close to origo, it will go up-right-down-left-down. * @param to Where to lay out to, coming from origo. * @param num_points Return value of how many points in the points array. * @param points The points in the layout. Free the array after use. The * passed in is ignored and overwritten, so should be NULL. * @return The badness of this layout. * * \ingroup Autorouting */ static real autoroute_layout_parallel(Point *to, guint *num_points, Point **points) { Point *ps = NULL; if (fabs(to->x) > MIN_DIST) { real top = MIN(-MIN_DIST, to->y-MIN_DIST); /* printf("Doing parallel layout: Wide\n"); */ *num_points = 4; ps = g_new0(Point, *num_points); /* points[0] is 0,0 */ ps[1].x = to->x/2; ps[1].y = top; ps[2].x = to->x/2; ps[2].y = top; ps[3] = *to; } else if (to->y > 0) { /* Close together, end below */ real top = -MIN_DIST; real off = to->x+MIN_DIST*(to->x>0?1.0:-1.0); real bottom = to->y-MIN_DIST; /* printf("Doing parallel layout: Narrow\n"); */ *num_points = 6; ps = g_new0(Point, *num_points); /* points[0] is 0,0 */ ps[1].y = top; ps[2].x = off; ps[2].y = top; ps[3].x = off; ps[3].y = bottom; ps[4].x = to->x; ps[4].y = bottom; ps[5] = *to; } else { real top = to->y-MIN_DIST; real off = MIN_DIST*(to->x>0?-1.0:1.0); real bottom = -MIN_DIST; /* printf("Doing parallel layout: Narrow\n"); */ *num_points = 6; ps = g_new0(Point, *num_points); /* points[0] is 0,0 */ ps[1].y = bottom; ps[2].x = off; ps[2].y = bottom; ps[3].x = off; ps[3].y = top; ps[4].x = to->x; ps[4].y = top; ps[5] = *to; } *points = ps; return calculate_badness(ps, *num_points); }
/** Do layout for the case where the directions are orthogonal to each other. * If both x and y of to are far enough from origo, this will be a simple * bend, otherwise it will be a question-mark style line. * @param to Where to lay out to, coming from origo. * @param enddir What direction the endpoint goes, either east or west. * @param num_points Return value of how many points in the points array. * @param points The points in the layout. Free the array after use. The * passed in is ignored and overwritten, so should be NULL. * @returns The badness of this layout. */ static real autoroute_layout_orthogonal(Point *to, int enddir, guint *num_points, Point **points) { /* This one doesn't consider enddir yet, not more complex layouts. */ Point *ps = NULL; real dirmult = (enddir==DIR_WEST?1.0:-1.0); if (to->y < -MIN_DIST) { if (dirmult*to->x > MIN_DIST) { /* printf("Doing orthogonal layout: Three-way\n"); */ *num_points = 3; ps = g_new0(Point, *num_points); /* points[0] is 0,0 */ ps[1].y = to->y; ps[2] = *to; } else { real off; if (dirmult*to->x > 0) off = -dirmult*MIN_DIST; else off = -dirmult*(MIN_DIST+fabs(to->x)); *num_points = 5; ps = g_new0(Point, *num_points); ps[1].y = -MIN_DIST; ps[2].x = off; ps[2].y = -MIN_DIST; ps[3].x = off; ps[3].y = to->y; ps[4] = *to; } } else { if (dirmult*to->x > 2*MIN_DIST) { real mid = to->x/2; *num_points = 5; ps = g_new0(Point, *num_points); ps[1].y = -MIN_DIST; ps[2].x = mid; ps[2].y = -MIN_DIST; ps[3].x = mid; ps[3].y = to->y; ps[4] = *to; } else { real off; if (dirmult*to->x > 0) off = -dirmult*MIN_DIST; else off = -dirmult*(MIN_DIST+fabs(to->x)); *num_points = 5; ps = g_new0(Point, *num_points); ps[1].y = -MIN_DIST; ps[2].x = off; ps[2].y = -MIN_DIST; ps[3].x = off; ps[3].y = to->y; ps[4] = *to; } } /* printf("Doing orthogonal layout\n"); */ *points = ps; return calculate_badness(ps, *num_points); }
/** Inspect a host's metering data to determine its current status * and problems, then write it to disk. * \param host The host to inspect. */ void watchthread_handle_host (host *host) { int problemcount = 0; double totalbadness = 0.0; time_t tnow = time (NULL); meter *m = host->first; meterwatch *w; watchadjust *adj = NULL; watchtrigger maxtrigger = WATCH_NONE; char label[16]; char uuidstr[40]; pthread_rwlock_wrlock (&host->lock); /* We'll store the status information as a meter itself */ meterid_t mid_status = makeid ("status",MTYPE_STR,0); meter *m_status = host_get_meter (host, mid_status); fstring ostatus = meter_get_str (m_status, 0); meter_setcount (m_status, 0); if (ostatus.str[0] == 0) strcpy (ostatus.str, "UNSET"); /* If the data is stale, don't add to badness, just set the status. */ if ((tnow - host->lastmodified) > 80) { if (strcmp (ostatus.str, "STALE") != 0) { uuid2str (host->uuid, uuidstr); log_info ("Status change host <%s> %s -> STALE", uuidstr, ostatus.str); tenant_set_notification (host->tenant, true, "STALE", host->uuid); } meter_set_str (m_status, 0, "STALE"); } else { /* Figure out badness for each meter, and add to host */ while (m) { m->badness = 0.0; int handled = 0; /* Get host-level adjustments in place */ adj = adjustlist_find (&host->adjust, m->id); /* First go over the tenant-defined watchers */ pthread_mutex_lock (&host->tenant->watch.mutex); w = host->tenant->watch.first; while (w) { if ((w->id & MMASK_NAME) == (m->id & MMASK_NAME)) { m->badness += calculate_badness (m, w, adj, &maxtrigger); handled = 1; } w = w->next; } pthread_mutex_unlock (&host->tenant->watch.mutex); /* If the tenant didn't have anything suitable, go over the global watchlist */ if (! handled) { pthread_mutex_lock (&APP.watch.mutex); w = APP.watch.first; while (w) { if ((w->id & MMASK_NAME) == (m->id & MMASK_NAME)) { m->badness += calculate_badness (m, w, adj, &maxtrigger); handled = 1; } w = w->next; } pthread_mutex_unlock (&APP.watch.mutex); } if (m->badness) problemcount++; totalbadness += m->badness; m = m->next; } /* Don't raise a CRIT alert on a WARN condition */ switch (maxtrigger) { case WATCH_NONE: totalbadness = 0.0; break; case WATCH_WARN: if (host->badness > 50.0) totalbadness = 0.0; break; case WATCH_ALERT: if (host->badness > 90.0) totalbadness = 0.0; break; case WATCH_CRIT: if (host->badness > 150.0) totalbadness = 0.0; break; } host->badness += totalbadness; /* Put up the problems as a meter as well */ meterid_t mid_problems = makeid ("problems",MTYPE_STR,0); meter *m_problems = host_get_meter (host, mid_problems); /* While we're looking at it, consider the current badness, if there are no problems, it should be going down. */ if (! problemcount) { if (host->badness > 100.0) host->badness = host->badness/2.0; else if (host->badness > 1.0) host->badness = host->badness *0.75; else host->badness = 0.0; meter_set_empty_array (m_problems); } else { /* If we reached the top, current level may still be out of its league, so allow it to decay slowly */ if (totalbadness == 0.0) host->badness *= 0.9; /* Fill in the problem array */ int i=0; meter_setcount (m_problems, problemcount); m = host->first; while (m && (i<16)) { if (m->badness > 0.00) { id2str (m->id, label); meter_set_str (m_problems, i++, label); } m = m->next; } } meterid_t mid_badness = makeid ("badness",MTYPE_FRAC,0); meter *m_badness = host_get_meter (host, mid_badness); meter_setcount (m_badness, 0); meter_set_frac (m_badness, 0, host->badness); const char *nstatus = "UNSET"; /* Convert badness to a status text */ if (host->badness < 30.0) nstatus = "OK"; else if (host->badness < 80.0) nstatus = "WARN"; else if (host->badness < 120.0) nstatus = "ALERT"; else nstatus = "CRIT"; if (strcmp (nstatus, ostatus.str) != 0) { uuid2str (host->uuid, uuidstr); log_info ("Status change host <%s> %s -> %s", uuidstr, ostatus.str, nstatus); bool isproblem = (host->badness>= 80.0); tenant_set_notification (host->tenant, isproblem, nstatus, host->uuid); } meter_set_str (m_status, 0, nstatus); } /* Write to db */ if (db_open (APP.writedb, host->tenant->uuid, NULL)) { db_save_record (APP.writedb, tnow, host); db_close (APP.writedb); } pthread_rwlock_unlock (&host->lock); /* for tallying the summaries we only need read access */ if (! host->tenant) return; pthread_rwlock_rdlock (&host->lock); m = host->first; while (m) { summaryinfo_add_meterdata (&host->tenant->summ, m->id, &m->d); m = m->next; } pthread_rwlock_unlock (&host->lock); }