summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crawler.c133
-rw-r--r--crawler.h2
-rw-r--r--items.c36
-rw-r--r--items.h1
-rw-r--r--logger.c2
-rw-r--r--memcached.h2
6 files changed, 106 insertions, 70 deletions
diff --git a/crawler.c b/crawler.c
index 93f7e1a..8f2c741 100644
--- a/crawler.c
+++ b/crawler.c
@@ -78,12 +78,14 @@ crawler_module_reg_t crawler_metadump_mod = {
.needs_client = true
};
-crawler_module_reg_t *crawler_mod_regs[2] = {
+crawler_module_reg_t *crawler_mod_regs[3] = {
+ &crawler_expired_mod,
&crawler_expired_mod,
&crawler_metadump_mod
};
crawler_module_t active_crawler_mod;
+enum crawler_run_type active_crawler_type;
static crawler crawlers[LARGEST_ID];
@@ -138,8 +140,8 @@ static int crawler_expired_init(crawler_module_t *cm, void *data) {
cm->data = d;
}
pthread_mutex_lock(&d->lock);
- memset(&d->crawlerstats, 0, sizeof(crawlerstats_t) * MAX_NUMBER_OF_SLAB_CLASSES);
- for (int x = 0; x < MAX_NUMBER_OF_SLAB_CLASSES; x++) {
+ memset(&d->crawlerstats, 0, sizeof(crawlerstats_t) * POWER_LARGEST);
+ for (int x = 0; x < POWER_LARGEST; x++) {
d->crawlerstats[x].start_time = current_time;
d->crawlerstats[x].run_complete = false;
}
@@ -150,8 +152,8 @@ static int crawler_expired_init(crawler_module_t *cm, void *data) {
static void crawler_expired_doneclass(crawler_module_t *cm, int slab_cls) {
struct crawler_expired_data *d = (struct crawler_expired_data *) cm->data;
pthread_mutex_lock(&d->lock);
- d->crawlerstats[CLEAR_LRU(slab_cls)].end_time = current_time;
- d->crawlerstats[CLEAR_LRU(slab_cls)].run_complete = true;
+ d->crawlerstats[slab_cls].end_time = current_time;
+ d->crawlerstats[slab_cls].run_complete = true;
pthread_mutex_unlock(&d->lock);
}
@@ -171,10 +173,9 @@ static void crawler_expired_finalize(crawler_module_t *cm) {
* main thread's values too much. Should rethink again.
*/
static void crawler_expired_eval(crawler_module_t *cm, item *search, uint32_t hv, int i) {
- int slab_id = CLEAR_LRU(i);
struct crawler_expired_data *d = (struct crawler_expired_data *) cm->data;
pthread_mutex_lock(&d->lock);
- crawlerstats_t *s = &d->crawlerstats[slab_id];
+ crawlerstats_t *s = &d->crawlerstats[i];
int is_flushed = item_is_flushed(search);
if ((search->exptime != 0 && search->exptime < current_time)
|| is_flushed) {
@@ -393,8 +394,14 @@ static void *item_crawler_thread(void *arg) {
}
if (crawls_persleep-- <= 0 && settings.lru_crawler_sleep) {
+ pthread_mutex_unlock(&lru_crawler_lock);
usleep(settings.lru_crawler_sleep);
+ pthread_mutex_lock(&lru_crawler_lock);
crawls_persleep = settings.crawls_persleep;
+ } else if (!settings.lru_crawler_sleep) {
+ // TODO: only cycle lock every N?
+ pthread_mutex_unlock(&lru_crawler_lock);
+ pthread_mutex_lock(&lru_crawler_lock);
}
}
}
@@ -414,6 +421,7 @@ static void *item_crawler_thread(void *arg) {
if (settings.verbose > 2)
fprintf(stderr, "LRU crawler thread sleeping\n");
+
STATS_LOCK();
stats_state.lru_crawler_running = false;
STATS_UNLOCK();
@@ -477,38 +485,29 @@ int start_item_crawler_thread(void) {
* LRU every time.
*/
static int do_lru_crawler_start(uint32_t id, uint32_t remaining) {
- int i;
- uint32_t sid;
- uint32_t tocrawl[3];
+ uint32_t sid = id;
int starts = 0;
- tocrawl[0] = id | HOT_LRU;
- tocrawl[1] = id | WARM_LRU;
- tocrawl[2] = id | COLD_LRU;
-
- for (i = 0; i < 3; i++) {
- sid = tocrawl[i];
- pthread_mutex_lock(&lru_locks[sid]);
- // TODO: Pretty sure this is a needless optimization.
- //if (tails[sid] != NULL) {
- if (settings.verbose > 2)
- fprintf(stderr, "Kicking LRU crawler off for LRU %u\n", sid);
- crawlers[sid].nbytes = 0;
- crawlers[sid].nkey = 0;
- crawlers[sid].it_flags = 1; /* For a crawler, this means enabled. */
- crawlers[sid].next = 0;
- crawlers[sid].prev = 0;
- crawlers[sid].time = 0;
- crawlers[sid].remaining = remaining;
- crawlers[sid].slabs_clsid = sid;
- crawlers[sid].reclaimed = 0;
- crawlers[sid].unfetched = 0;
- crawlers[sid].checked = 0;
- do_item_linktail_q((item *)&crawlers[sid]);
- crawler_count++;
- starts++;
- //}
- pthread_mutex_unlock(&lru_locks[sid]);
+
+ pthread_mutex_lock(&lru_locks[sid]);
+ if (crawlers[sid].it_flags == 0) {
+ if (settings.verbose > 2)
+ fprintf(stderr, "Kicking LRU crawler off for LRU %u\n", sid);
+ crawlers[sid].nbytes = 0;
+ crawlers[sid].nkey = 0;
+ crawlers[sid].it_flags = 1; /* For a crawler, this means enabled. */
+ crawlers[sid].next = 0;
+ crawlers[sid].prev = 0;
+ crawlers[sid].time = 0;
+ crawlers[sid].remaining = remaining;
+ crawlers[sid].slabs_clsid = sid;
+ crawlers[sid].reclaimed = 0;
+ crawlers[sid].unfetched = 0;
+ crawlers[sid].checked = 0;
+ do_item_linktail_q((item *)&crawlers[sid]);
+ crawler_count++;
+ starts++;
}
+ pthread_mutex_unlock(&lru_locks[sid]);
if (starts) {
STATS_LOCK();
stats_state.lru_crawler_running = true;
@@ -537,31 +536,48 @@ int lru_crawler_start(uint8_t *ids, uint32_t remaining,
const enum crawler_run_type type, void *data,
void *c, const int sfd) {
int starts = 0;
- if (pthread_mutex_trylock(&lru_crawler_lock) != 0) {
+ bool is_running;
+ static rel_time_t block_ae_until = 0;
+ pthread_mutex_lock(&lru_crawler_lock);
+ STATS_LOCK();
+ is_running = stats_state.lru_crawler_running;
+ STATS_UNLOCK();
+ if (is_running &&
+ !(type == CRAWLER_AUTOEXPIRE && active_crawler_type == CRAWLER_AUTOEXPIRE)) {
+ pthread_mutex_unlock(&lru_crawler_lock);
+ block_ae_until = current_time + 60;
return -1;
}
- /* Configure the module */
- assert(crawler_mod_regs[type] != NULL);
- active_crawler_mod.mod = crawler_mod_regs[type];
- if (active_crawler_mod.mod->init != NULL) {
- active_crawler_mod.mod->init(&active_crawler_mod, data);
+ if (type == CRAWLER_AUTOEXPIRE && block_ae_until > current_time) {
+ pthread_mutex_unlock(&lru_crawler_lock);
+ return -1;
}
- if (active_crawler_mod.mod->needs_client) {
- if (c == NULL || sfd == 0) {
- pthread_mutex_unlock(&lru_crawler_lock);
- return -2;
+
+ /* Configure the module */
+ if (!is_running) {
+ assert(crawler_mod_regs[type] != NULL);
+ active_crawler_mod.mod = crawler_mod_regs[type];
+ active_crawler_type = type;
+ if (active_crawler_mod.mod->init != NULL) {
+ active_crawler_mod.mod->init(&active_crawler_mod, data);
}
- if (lru_crawler_set_client(&active_crawler_mod, c, sfd) != 0) {
- pthread_mutex_unlock(&lru_crawler_lock);
- return -2;
+ if (active_crawler_mod.mod->needs_client) {
+ if (c == NULL || sfd == 0) {
+ pthread_mutex_unlock(&lru_crawler_lock);
+ return -2;
+ }
+ if (lru_crawler_set_client(&active_crawler_mod, c, sfd) != 0) {
+ pthread_mutex_unlock(&lru_crawler_lock);
+ return -2;
+ }
}
}
- for (int sid = POWER_SMALLEST; sid < MAX_NUMBER_OF_SLAB_CLASSES; sid++) {
- if (ids[sid]) {
+ /* we allow the autocrawler to restart sub-LRU's before completion */
+ for (int sid = POWER_SMALLEST; sid < POWER_LARGEST; sid++) {
+ if (ids[sid])
starts += do_lru_crawler_start(sid, remaining);
- }
}
if (starts) {
pthread_cond_signal(&lru_crawler_cond);
@@ -578,12 +594,12 @@ enum crawler_result_type lru_crawler_crawl(char *slabs, const enum crawler_run_t
char *b = NULL;
uint32_t sid = 0;
int starts = 0;
- uint8_t tocrawl[MAX_NUMBER_OF_SLAB_CLASSES];
+ uint8_t tocrawl[POWER_LARGEST];
/* FIXME: I added this while debugging. Don't think it's needed? */
- memset(tocrawl, 0, sizeof(uint8_t) * MAX_NUMBER_OF_SLAB_CLASSES);
+ memset(tocrawl, 0, sizeof(uint8_t) * POWER_LARGEST);
if (strcmp(slabs, "all") == 0) {
- for (sid = 0; sid < MAX_NUMBER_OF_SLAB_CLASSES; sid++) {
+ for (sid = 0; sid < POWER_LARGEST; sid++) {
tocrawl[sid] = 1;
}
} else {
@@ -596,7 +612,10 @@ enum crawler_result_type lru_crawler_crawl(char *slabs, const enum crawler_run_t
pthread_mutex_unlock(&lru_crawler_lock);
return CRAWLER_BADCLASS;
}
- tocrawl[sid] = 1;
+ tocrawl[sid | TEMP_LRU] = 1;
+ tocrawl[sid | HOT_LRU] = 1;
+ tocrawl[sid | WARM_LRU] = 1;
+ tocrawl[sid | COLD_LRU] = 1;
}
}
diff --git a/crawler.h b/crawler.h
index 7c7c1d2..ad30e66 100644
--- a/crawler.h
+++ b/crawler.h
@@ -14,7 +14,7 @@ typedef struct {
struct crawler_expired_data {
pthread_mutex_t lock;
- crawlerstats_t crawlerstats[MAX_NUMBER_OF_SLAB_CLASSES];
+ crawlerstats_t crawlerstats[POWER_LARGEST];
/* redundant with crawlerstats_t so we can get overall start/stop/done */
rel_time_t start_time;
rel_time_t end_time;
diff --git a/items.c b/items.c
index 6e36504..556ba5a 100644
--- a/items.c
+++ b/items.c
@@ -1333,19 +1333,18 @@ static int lru_maintainer_juggle(const int slabs_clsid) {
*/
static void lru_maintainer_crawler_check(struct crawler_expired_data *cdata, logger *l) {
int i;
- static rel_time_t next_crawls[MAX_NUMBER_OF_SLAB_CLASSES];
- static rel_time_t next_crawl_wait[MAX_NUMBER_OF_SLAB_CLASSES];
- uint8_t todo[MAX_NUMBER_OF_SLAB_CLASSES];
- memset(todo, 0, sizeof(uint8_t) * MAX_NUMBER_OF_SLAB_CLASSES);
+ static rel_time_t next_crawls[POWER_LARGEST];
+ static rel_time_t next_crawl_wait[POWER_LARGEST];
+ uint8_t todo[POWER_LARGEST];
+ memset(todo, 0, sizeof(uint8_t) * POWER_LARGEST);
bool do_run = false;
- if (!cdata->crawl_complete) {
- return;
- }
- for (i = POWER_SMALLEST; i < MAX_NUMBER_OF_SLAB_CLASSES; i++) {
+ // TODO: If not segmented LRU, skip non-cold
+ for (i = POWER_SMALLEST; i < POWER_LARGEST; i++) {
crawlerstats_t *s = &cdata->crawlerstats[i];
/* We've not successfully kicked off a crawl yet. */
if (s->run_complete) {
+ char *lru_name = "na";
pthread_mutex_lock(&cdata->lock);
int x;
/* Should we crawl again? */
@@ -1378,7 +1377,24 @@ static void lru_maintainer_crawler_check(struct crawler_expired_data *cdata, log
}
next_crawls[i] = current_time + next_crawl_wait[i] + 5;
- LOGGER_LOG(l, LOG_SYSEVENTS, LOGGER_CRAWLER_STATUS, NULL, i, (unsigned long long)low_watermark,
+ switch (GET_LRU(i)) {
+ case HOT_LRU:
+ lru_name = "hot";
+ break;
+ case WARM_LRU:
+ lru_name = "warm";
+ break;
+ case COLD_LRU:
+ lru_name = "cold";
+ break;
+ case TEMP_LRU:
+ lru_name = "temp";
+ break;
+ }
+ LOGGER_LOG(l, LOG_SYSEVENTS, LOGGER_CRAWLER_STATUS, NULL,
+ CLEAR_LRU(i),
+ lru_name,
+ (unsigned long long)low_watermark,
(unsigned long long)available_reclaims,
(unsigned int)since_run,
next_crawls[i] - current_time,
@@ -1396,7 +1412,7 @@ static void lru_maintainer_crawler_check(struct crawler_expired_data *cdata, log
}
}
if (do_run) {
- lru_crawler_start(todo, settings.lru_crawler_tocrawl, CRAWLER_EXPIRED, cdata, NULL, 0);
+ lru_crawler_start(todo, settings.lru_crawler_tocrawl, CRAWLER_AUTOEXPIRE, cdata, NULL, 0);
}
}
diff --git a/items.h b/items.h
index 6683bf7..fd573aa 100644
--- a/items.h
+++ b/items.h
@@ -4,6 +4,7 @@
#define TEMP_LRU 192
#define CLEAR_LRU(id) (id & ~(3<<6))
+#define GET_LRU(id) (id & (3<<6))
/* See items.c */
uint64_t get_cas_id(void);
diff --git a/logger.c b/logger.c
index 892bea8..b6072f0 100644
--- a/logger.c
+++ b/logger.c
@@ -50,7 +50,7 @@ static const entry_details default_entries[] = {
[LOGGER_ITEM_GET] = {LOGGER_ITEM_GET_ENTRY, 512, LOG_FETCHERS, NULL},
[LOGGER_ITEM_STORE] = {LOGGER_ITEM_STORE_ENTRY, 512, LOG_MUTATIONS, NULL},
[LOGGER_CRAWLER_STATUS] = {LOGGER_TEXT_ENTRY, 512, LOG_SYSEVENTS,
- "type=lru_crawler crawler=%d low_mark=%llu next_reclaims=%llu since_run=%u next_run=%d elapsed=%u examined=%llu reclaimed=%llu"
+ "type=lru_crawler crawler=%d lru=%s low_mark=%llu next_reclaims=%llu since_run=%u next_run=%d elapsed=%u examined=%llu reclaimed=%llu"
}
};
diff --git a/memcached.h b/memcached.h
index b1abbda..65d8f60 100644
--- a/memcached.h
+++ b/memcached.h
@@ -429,7 +429,7 @@ typedef struct _stritem {
// TODO: If we eventually want user loaded modules, we can't use an enum :(
enum crawler_run_type {
- CRAWLER_EXPIRED=0, CRAWLER_METADUMP
+ CRAWLER_AUTOEXPIRE=0, CRAWLER_EXPIRED, CRAWLER_METADUMP
};
typedef struct {