void *malloc (size_t size) { void *ret; int pool_idx; if (malloc_base == NULL || size == 0) { ret = NULL; } else if (size >= MAX_ELEM_SIZE) { ret = big_malloc((size + PAGE_SIZE - 1) / PAGE_SIZE); } else { if (size <= MIN_ELEM_SIZE) pool_idx = 0; else { pool_idx = get_pool_idx(size); } ret = pool_malloc(pool_idx); } if (ret != NULL) memset(ret, 0, size); #if 0 memory_dump(); printf("%s(%d) => %p\n", __func__, size, ret); #endif return ret; }
static void insert_grace(char *test, time_t grace) { struct gracetime *gt = big_malloc("insert_grace", sizeof *gt); gt->test = big_strdup("insert_grace", test); gt->grace = grace; gt->next = gracetime; gracetime = gt; }
static struct option *insert_option(char *n) { struct option *o = big_malloc("insert_option", sizeof *o); o->name = big_strdup("insert_option", n); o->next = options; options = o; return o; }
void * malloc(size_t size) { if (size <= SMALL_BLOCK) { return (void *) small_malloc(size); } if (size >= BIG_BLOCK) { return (void *) big_malloc(size); } return (void *) medium_malloc(size); }
void *realloc (void *area, size_t new_size) { void *new_area; page_descr_t *pool_descr, *cache_descr; size_t size; int pool_idx, new_pool_idx; if (malloc_base == NULL || new_size == 0) { free(area); return NULL; } if (area == NULL) return malloc(new_size); cache_descr = page_cache_get_descr(PAGE(area)); if (cache_descr == NULL) { /* Given area is not valid */ return NULL; } pool_idx = page_cache_pool_idx(cache_descr); if (new_size >= MAX_ELEM_SIZE) { new_pool_idx = POOL_MAX; if (pool_idx == POOL_MAX) return big_realloc(cache_descr, new_size); } else { if (new_size <= MIN_ELEM_SIZE) new_pool_idx = 0; else new_pool_idx = get_pool_idx(size); if (pool_idx == new_pool_idx) return area; } /* Common case: alloc, copy & free */ if (new_pool_idx == POOL_MAX) new_area = big_malloc((new_size + PAGE_SIZE - 1) / PAGE_SIZE); else new_area = pool_malloc(new_pool_idx); if (new_area == NULL) return NULL; if (pool_idx == POOL_MAX) { pool_descr = page_cache_page_descr(cache_descr); size = pool_descr->nb * PAGE_SIZE; } else { size = MIN_ELEM_SIZE << pool_idx; } memcpy(new_area, area, size); if (pool_idx == POOL_MAX) big_free(cache_descr); else pool_free(cache_descr, area); return new_area; }
unused static void *big_realloc (page_descr_t *cache_descr, int new_size) { void *new_area; page_descr_t *pool_descr; unsigned long new_nb; pool_descr = page_cache_page_descr(cache_descr); new_nb = (new_size + PAGE_SIZE - 1) / PAGE_SIZE; if (new_nb == pool_descr->nb) { new_area = cache_descr->addr; } else { new_area = big_malloc(new_size); memcpy(new_area, cache_descr->addr, pool_descr->nb * PAGE_SIZE); big_free(cache_descr); } return new_area; }
void * malloc(unsigned int size) { if (!malloc_initialized) malloc_init(); if (size == 0) return 0; /* so says ANSI */ /* use the special allocator for small sizes */ if (size <= 56) return small_malloc(size); /* use the standard free list for large sizes */ return big_malloc(size); }
//void mrsend(char *p) void mrsend(char *machine, char *test, char *color, char *message) { struct display *mp; struct sockaddr_in my_addr; struct linger l_optval; unsigned long nonblock; char *p = NULL; int is; if (debug > 1) mrlog("mrsend(%s, %s, %s, %s)", machine, test, color, message); #if 0 n = sscanf(p, "status %199[^.].%99[^ ] %99s", machine, test, color); if (n != 3) { mrlog("Bogus string in mrsend, process anyway"); if (debug) mrlog("%s", p); } #endif is = insert_status(machine, test, color); if (is == 0) { if (debug) mrlog("mrsend: no change, nothing to do"); return; } if (!start_winsock()) return; /* Prepare the report */ p = big_malloc("mrsend()", report_size+1); p[0] = '\0'; if (is == 1) { snprcat(p, report_size, "status %s.%s green %s", machine, test, message); } else { snprcat(p, report_size, "status %s.%s %s %s", machine, test, color, message); } for (mp = mrdisplay; mp; mp = mp->next) { mp->s = -1; } for (mp = mrdisplay; mp; mp = mp->next) { mp->s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (mp->s == -1) { mrlog("mrsend: socket failed: %d", WSAGetLastError()); continue; } memset(&my_addr, 0, sizeof(my_addr)); my_addr.sin_family = AF_INET; my_addr.sin_port = 0; my_addr.sin_addr.s_addr = inet_addr(bind_addr); if (bind(mp->s, (struct sockaddr *)&my_addr, sizeof my_addr) < 0) { mrlog("mrsend: bind(%s) failed: [%d]", bind_addr, WSAGetLastError()); closesocket(mp->s); mp->s = -1; continue; } l_optval.l_onoff = 1; l_optval.l_linger = 5; nonblock = 1; if (ioctlsocket(mp->s, FIONBIO, &nonblock) == SOCKET_ERROR) { mrlog("mrsend: ioctlsocket failed: %d", WSAGetLastError()); closesocket(mp->s); mp->s = -1; continue; } if (setsockopt(mp->s, SOL_SOCKET, SO_LINGER, (const char*)&l_optval, sizeof(l_optval)) == SOCKET_ERROR) { mrlog("mrsend: setsockopt failed: %d", WSAGetLastError()); closesocket(mp->s); mp->s = -1; continue; } if (debug) mrlog("Using address %s, port %d\n", inet_ntoa(mp->in_addr.sin_addr), ntohs(mp->in_addr.sin_port)); if (connect(mp->s, (struct sockaddr *)&mp->in_addr, sizeof(mp->in_addr)) == SOCKET_ERROR) { if (WSAGetLastError() != WSAEWOULDBLOCK) { mrlog("mrsend: connect: %d", WSAGetLastError()); l_optval.l_onoff = 0; l_optval.l_linger = 0; setsockopt(mp->s, SOL_SOCKET, SO_LINGER, (const char*)&l_optval, sizeof(l_optval)); closesocket(mp->s); mp->s = -1; continue; } } mp->pdata = p; mp->remaining = strlen(p); } time_t start_time = time(NULL); for(;;) { struct timeval timeo; fd_set wfds; int len; int tot_remaining; timeo.tv_sec = 1; timeo.tv_usec = 0; FD_ZERO(&wfds); tot_remaining = 0; for (mp = mrdisplay; mp; mp = mp->next) { if (mp->s != -1) { if (mp->remaining > 0) { FD_SET(mp->s, &wfds); tot_remaining += mp->remaining; } } } if (tot_remaining == 0) { /* all data sent to displays */ goto cleanup; } if (time(NULL) > start_time + 10 || time(NULL) < start_time) { mrlog("mrsend: send loop timed out"); /* this should not take more than 10 seconds. Network problem, so bail out */ goto cleanup; } select(255 /* ignored on winsock */, NULL, &wfds, NULL, &timeo); for (mp = mrdisplay; mp; mp = mp->next) { if (mp->s != -1) { if (mp->remaining > 0) { len = send(mp->s, mp->pdata, mp->remaining, 0); if (len == SOCKET_ERROR) { continue; } mp->pdata += len; mp->remaining -= len; if (mp->remaining == 0) { shutdown(mp->s, SD_BOTH); } } } } } cleanup: /* initiate socket shutdowns */ for (mp = mrdisplay; mp; mp = mp->next) { if (mp->s != -1) { shutdown(mp->s, SD_BOTH); } } /* gracefully terminate sockets, finally applying force */ for (mp = mrdisplay; mp; mp = mp->next) { int i; if (mp->s != -1) { for (i = 0; i < 10; i++) { if (closesocket(mp->s) == WSAEWOULDBLOCK) { Sleep(1000); /* wait for all data to be sent */ } } /* force the socket shut */ l_optval.l_onoff = 0; l_optval.l_linger = 0; setsockopt(mp->s, SOL_SOCKET, SO_LINGER, (const char*)&l_optval, sizeof(l_optval)); closesocket(mp->s); mp->s = -1; } } big_free("mrsend()", p); }
/* Insert status into list. Return 0 if color is unchanged and sleep time is not exceeded. Return 1 if color is non-green but grace time is not exceeded. Return 2 otherwise. */ static int insert_status(char *machine, char *test, char *color) { struct teststatus *s; time_t now = time(NULL); time_t grace = lookup_grace(test); if (debug > 1) mrlog("insert_status(%s, %s, %s)", machine, test, color); for (s = teststatus; s; s = s->next) { if (!strcmp(machine, s->machine) && !strcmp(test, s->test)) { if (debug) mrlog("insert_status found match"); break; } } if (s == NULL) { /* We have never seen this test before. Allocate a new structure with initial values and tell mrsend to report the real status to the bbd. */ s = big_malloc("insert_status: node", sizeof *s); s->machine = big_strdup("insert_status: machine", machine); s->test = big_strdup("insert_status: test", test); s->next = teststatus; if (debug) mrlog("insert_status: new test"); s->color = big_strdup("insert_status: color", color); s->last = now; s->grace = 0; teststatus = s; return 2; } if (!strcmp(color, s->color)) { /* If status is unchanged, check the time. */ if (now < s->last) { /* Someone adjusted the time or something. Reset and tell mrsend to report the real status. */ mrlog("insert_status: Time has decreased!"); s->last = now; s->grace = 0; return 2; } if (now-s->last >= mrsleep) { /* We must send a report or the display will turn purple. */ if (debug) mrlog("insert_status: mrsleep exceeded"); s->last = now; s->grace = 0; return 2; } /* No need to do anything. */ return 0; } /* We now know that the current status is different from the one last reported to the bbd. */ if (!strcmp(color, "green")) { /* If the new status is green, insert the new status, reset gracetime and report the real status. */ big_free("insert_status: color", s->color); s->color = big_strdup("insert_status: color", color); s->last = now; s->grace = 0; return 2; } if (strcmp(s->color, "green")) { /* If the old status was anything but green, insert the new status, reset gracetime and report the real status. */ big_free("insert_status: color", s->color); s->color = big_strdup("insert_status: color", color); s->last = now; s->grace = 0; return 2; } /* We now know that the old status was green and the new status is non-green. */ if (s->grace == 0) { /* Start the clock ticking. */ s->grace = now+grace; } if (now >= s->grace) { /* Grace time expired, send a real status report. */ big_free("insert_status: color", s->color); s->color = big_strdup("insert_status: color", color); s->last = now; return 2; } /* Sit on our hands for a while. Tell mrsend to send a green status to the bbd. */ s->last = now; return 1; }
static void readcfg(void) { char b[256], key[256], value[256], *p; struct display *mp; int i; if (debug > 1) mrlog("readcfg()"); /* Set all defaults */ strlcpy(mrmachine, "localhost", sizeof mrmachine); mrport = 1984; while (mrdisplay) { mp = mrdisplay; mrdisplay = mp->next; big_free("readcfg: display", mp); } free_grace(); free_options(); mrsleep = 300; mrloop = INT_MAX; bootyellow = 60; bootred = 30; dfyellow = 90; dfred = 95; cpuyellow = 80; cpured = 90; memyellow = 100; memred = 100; msgage = 3600; memsize = MEMSIZE; pickupdir[0] = '\0'; if (logfp) big_fclose("readcfg:logfile", logfp); logfp = NULL; for (i = 0; get_cfg("mrbig", b, sizeof b, i); i++) { if (b[0] == '#') continue; if (sscanf(b, "%s %[^\n]", key, value) == 2) { if (!strcmp(key, "machine")) { strlcpy(mrmachine, value, sizeof mrmachine); } else if (!strcmp(key, "port")) { mrport = atoi(value); } else if (!strcmp(key, "display")) { mp = big_malloc("readcfg: display", sizeof *mp); memset(&mp->in_addr, 0, sizeof mp->in_addr); mp->in_addr.sin_family = AF_INET; p = strchr(value, ':'); if (p) { *p++ = '\0'; mp->in_addr.sin_port = htons(atoi(p)); } else { mp->in_addr.sin_port = htons(mrport); } mp->in_addr.sin_addr.s_addr = inet_addr(value); mp->next = mrdisplay; mrdisplay = mp; } else if (!strcmp(key, "sleep")) { mrsleep = atoi(value); } else if (!strcmp(key, "loop")) { mrloop = atoi(value); } else if (!strcmp(key, "bootyellow")) { bootyellow = atoi(value); } else if (!strcmp(key, "bootred")) { bootred = atoi(value); } else if (!strcmp(key, "debug")) { debug = atoi(value); } else if (!strcmp(key, "cpuyellow")) { cpuyellow = atoi(value); } else if (!strcmp(key, "cpured")) { cpured = atoi(value); } else if (!strcmp(key, "dfyellow")) { dfyellow = atof(value); } else if (!strcmp(key, "dfred")) { dfred = atof(value); } else if (!strcmp(key, "memyellow")) { memyellow = atof(value); } else if (!strcmp(key, "memred")) { memred = atof(value); } else if (!strcmp(key, "cfgdir")) { strlcpy(cfgdir, value, sizeof cfgdir); } else if (!strcmp(key, "msgage")) { msgage = atoi(value); } else if (!strcmp(key, "pickupdir")) { strlcpy(pickupdir, value, sizeof pickupdir); } else if (!strcmp(key, "logfile")) { logfp = big_fopen("readcfg:logfile", value, "a"); } else if (!strcmp(key, "gracetime")) { char test[1000]; int grace = 0; sscanf(value, "%s %d", test, &grace); insert_grace(test, grace); } else if (!strcmp(key, "report_size")) { report_size = atoi(value); } else if (!strcmp(key, "option")) { insert_option(value); } else if (!strcmp(key, "memsize")) { memsize = atoi(value); } else if (!strcmp(key, "set")) { char key[1000], value[1000]; key[0] = value[0] = '\0'; sscanf(value, "%s %s", key, value); mrlog("This doesn't actually do anything"); } } } /* Replace . with , in fqdn (historical reasons) */ for (p = mrmachine; *p; p++) { if (*p == '.') *p = ','; } /* Make sure the main loop executes at least every mrsleep seconds */ if (mrloop > mrsleep) mrloop = mrsleep; }
char *big_strdup(char *p, char *q) { char *a = big_malloc(p, strlen(q)+1); return strcpy(a, q); }