Updated Branches: refs/heads/master b076565a2 -> 4102e9868
TS-2257 Healthcheck plugin can stop watching some events. The issue is related to the wonky garbage collection. This moves all garbage collection to a dedicate "to-free list". Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/4102e986 Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/4102e986 Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/4102e986 Branch: refs/heads/master Commit: 4102e9868d4d5684bae712c4a02d298bf2cd09e6 Parents: b076565 Author: Leif Hedstrom <[email protected]> Authored: Thu Oct 3 07:52:40 2013 -0600 Committer: Leif Hedstrom <[email protected]> Committed: Thu Oct 3 07:52:40 2013 -0600 ---------------------------------------------------------------------- CHANGES | 2 + .../experimental/healthchecks/healthchecks.c | 62 +++++++++++--------- 2 files changed, 35 insertions(+), 29 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/4102e986/CHANGES ---------------------------------------------------------------------- diff --git a/CHANGES b/CHANGES index df4bf51..ee94a4b 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,8 @@ -*- coding: utf-8 -*- Changes with Apache Traffic Server 4.1.0 + *) [TS-2257] Healthcheck plugin can stop watching some events. + *) [TS-2260] Avoid flooding log when log host is down. *) [TS-2259] Introduce failover hosts for logging system. http://git-wip-us.apache.org/repos/asf/trafficserver/blob/4102e986/plugins/experimental/healthchecks/healthchecks.c ---------------------------------------------------------------------- diff --git a/plugins/experimental/healthchecks/healthchecks.c b/plugins/experimental/healthchecks/healthchecks.c index c7ae166..f8763d3 100644 --- a/plugins/experimental/healthchecks/healthchecks.c +++ b/plugins/experimental/healthchecks/healthchecks.c @@ -70,7 +70,7 @@ typedef struct HCFileData_t char body[MAX_BODY_LEN]; /* Body from fname. NULL means file is missing */ int b_len; /* Length of data */ time_t remove; /* Used for deciding when the old object can be permanently removed */ - struct HCFileData_t *_next; /* Only used when removing these bad boys */ + struct HCFileData_t *_next; /* Only used when these guys end up on the freelist */ } HCFileData; /* The only thing that should change in this struct is data, atomically swapping ptrs */ @@ -118,7 +118,7 @@ reload_status_file(HCFileInfo *info, HCFileData *data) { struct stat buf; - data->exists = 0; + memset(data, 0, sizeof(HCFileData)); if (!stat(info->fname, &buf)) { FILE *fd; @@ -126,16 +126,10 @@ reload_status_file(HCFileInfo *info, HCFileData *data) if ((data->b_len = fread(data->body, 1, MAX_BODY_LEN, fd)) > 0) { data->exists = 1; data->mtime = buf.st_mtime; - data->remove = 0; } fclose(fd); } } - if (!data->exists) { - data->body[0] = '\0'; - data->b_len = 0; - data->mtime = 0; - } } /* Find a HCDirEntry from the linked list */ @@ -190,7 +184,7 @@ hc_thread(void *data ATS_UNUSED) int fd = inotify_init(); HCDirEntry *dirs; int len; - HCFileData *fl = NULL; + HCFileData *fl_head = NULL; char buffer[INOTIFY_BUFLEN]; struct timeval last_free, now; @@ -200,31 +194,38 @@ hc_thread(void *data ATS_UNUSED) dirs = setup_watchers(fd); while (1) { + HCFileData *fdata = fl_head, *fdata_prev = NULL; int i = 0; - /* First clean out anything old from the freelist */ + /* Read the inotify events, blocking until we get something */ + len = read(fd, buffer, INOTIFY_BUFLEN); gettimeofday(&now, NULL); - if ((now.tv_sec - last_free.tv_sec) > FREELIST_TIMEOUT) { - HCFileData *fdata = fl, *prev_fdata = fl; - - TSDebug(PLUGIN_NAME, "Checking the freelist"); - memcpy(&last_free, &now, sizeof(struct timeval)); - while(fdata) { - if (fdata->remove > now.tv_sec) { - if (prev_fdata) - prev_fdata->_next = fdata->_next; - fdata = fdata->_next; + + /* The fl_head is a linked list of previously released data entries. They + are ordered "by time", so once we find one that is scheduled for deletion, + we can also delete all entries after it in the linked list. */ + while (fdata) { + if (fdata->remove < now.tv_sec) { + /* Now drop off the "tail" from the freelist */ + if (fdata_prev) + fdata_prev->_next = NULL; + else + fl_head = NULL; + + /* free() everything in the "tail" */ + do { + HCFileData *next = fdata->_next; + TSDebug(PLUGIN_NAME, "Cleaning up entry from frelist"); TSfree(fdata); - } else { - prev_fdata = fdata; - fdata = fdata->_next; - } + fdata = next; + } while (fdata); + break; /* Stop the loop, there's nothing else left to examine */ } + fdata_prev = fdata; + fdata = fdata->_next; } - /* Read the inotify events, blocking! */ - len = read(fd, buffer, INOTIFY_BUFLEN); if (len >= 0) { while (i < len) { struct inotify_event *event = (struct inotify_event *)&buffer[i]; @@ -248,12 +249,15 @@ hc_thread(void *data ATS_UNUSED) TSDebug(PLUGIN_NAME, "Delete file event (%d) on %s", event->mask, finfo->fname); finfo->wd = inotify_rm_watch(fd, finfo->wd); } + /* Load the new data and then swap this atomically */ memset(new_data, 0, sizeof(HCFileData)); reload_status_file(finfo, new_data); - finfo->data->_next = fl; - finfo->data->remove = now.tv_sec + FREELIST_TIMEOUT; - fl = finfo->data; ink_atomic_swap_ptr(&(finfo->data), new_data); + + /* Add the old data to the head of the freelist */ + new_data->remove = now.tv_sec + FREELIST_TIMEOUT; + new_data->_next = fl_head; + fl_head = new_data; } i += sizeof(struct inotify_event) + event->len; }
