Exemplo n.º 1
0
/** 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);
}
Exemplo n.º 2
0
/*!
 * \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);
}
Exemplo n.º 3
0
/** 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);
}
Exemplo n.º 4
0
/** 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);
}