Changeset 114 in svn for trunk/xcache.c


Ignore:
Timestamp:
2006-08-30T02:31:03+02:00 (9 years ago)
Author:
Xuefer
Message:

gc expired items, new ini: xcache.ttl xcache.gc_interval xcache.var_ttl xcache.var_maxttl xcache.var_gc_interval

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/xcache.c

    r113 r114  
    3939#include <assert.h>
    4040
     41#define VAR_ENTRY_EXPIRED(pentry) ((pentry)->ttl && XG(request_time) > pentry->ctime + (pentry)->ttl)
    4142#define CHECK(x, e) do { if ((x) == NULL) { zend_error(E_ERROR, "XCache: " e); goto err; } } while (0)
    4243#define LOCK(x) xc_lock(x->lck)
     
    6566static xc_hash_t xc_var_hentry = {0};
    6667
     68static zend_ulong xc_php_ttl    = 0;
     69static zend_ulong xc_var_maxttl = 0;
     70
     71enum { xc_deletes_gc_interval = 120 };
     72static zend_ulong xc_php_gc_interval = 0;
     73static zend_ulong xc_var_gc_interval = 0;
     74
    6775/* total size */
    6876static zend_ulong xc_php_size  = 0;
     
    162170}
    163171/* }}} */
     172static void xc_entry_remove_real_dmz(xc_entry_t *xce, xc_entry_t **pp TSRMLS_DC) /* {{{ */
     173{
     174    *pp = xce->next;
     175    xce->cache->entries_count --;
     176    if (xce->refcount == 0) {
     177        xc_entry_free_dmz(xce);
     178    }
     179    else {
     180        xce->next = xce->cache->deletes;
     181        xce->cache->deletes = xce;
     182        xce->dtime = XG(request_time);
     183        xce->cache->deletes_count ++;
     184    }
     185    return;
     186}
     187/* }}} */
    164188static void xc_entry_remove_dmz(xc_entry_t *xce TSRMLS_DC) /* {{{ */
    165189{
    166     xc_entry_t **last = &(xce->cache->entries[xce->hvalue]);
     190    xc_entry_t **pp = &(xce->cache->entries[xce->hvalue]);
    167191    xc_entry_t *p;
    168     for (p = *last; p; last = &(p->next), p = p->next) {
     192    for (p = *pp; p; pp = &(p->next), p = p->next) {
    169193        if (xc_entry_equal_dmz(xce, p)) {
    170             *last = p->next;
    171             xce->cache->entries_count ++;
    172             if (p->refcount == 0) {
    173                 xc_entry_free_dmz(p);
    174             }
    175             else {
    176                 p->next = p->cache->deletes;
    177                 p->cache->deletes = p;
    178                 p->dtime = XG(request_time);
    179                 xce->cache->deletes_count ++;
    180             }
     194            xc_entry_remove_real_dmz(xce, pp TSRMLS_CC);
    181195            return;
    182196        }
     
    219233#endif
    220234
     235/* helper function that loop through each entry */
     236#define XC_ENTRY_APPLY_FUNC(name) int name(xc_entry_t *entry TSRMLS_DC)
     237typedef XC_ENTRY_APPLY_FUNC((*cache_apply_dmz_func_t));
     238static void xc_entry_apply_dmz(xc_cache_t *cache, cache_apply_dmz_func_t apply_func TSRMLS_DC) /* {{{ */
     239{
     240    xc_entry_t *p, **pp;
     241    int i, c;
     242
     243    for (i = 0, c = cache->hentry->size; i < c; i ++) {
     244        pp = &(cache->entries[i]);
     245        for (p = *pp; p; p = p->next) {
     246            if (apply_func(p TSRMLS_CC)) {
     247                xc_entry_remove_real_dmz(p, pp TSRMLS_CC);
     248            }
     249            else {
     250                pp = &(p->next);
     251            }
     252        }
     253    }
     254}
     255/* }}} */
     256
     257#define XC_CACHE_APPLY_FUNC(name) void name(xc_cache_t *cache TSRMLS_DC)
     258/* call graph:
     259 * xc_php_gc_expires -> xc_gc_expires_var_one -> xc_entry_apply_dmz -> xc_gc_php_entry_expires_dmz
     260 * xc_var_gc_expires -> xc_gc_expires_one -> xc_entry_apply_dmz -> xc_gc_var_entry_expires_dmz
     261 */
     262static XC_ENTRY_APPLY_FUNC(xc_gc_php_entry_expires_dmz) /* {{{ */
     263{
     264    fprintf(stderr, "ttl %d, %d %d\n", XG(request_time), entry->atime, xc_php_ttl);
     265    if (XG(request_time) > entry->atime + xc_php_ttl) {
     266        return 1;
     267    }
     268    return 0;
     269}
     270/* }}} */
     271static XC_ENTRY_APPLY_FUNC(xc_gc_var_entry_expires_dmz) /* {{{ */
     272{
     273    if (VAR_ENTRY_EXPIRED(entry)) {
     274        return 1;
     275    }
     276    return 0;
     277}
     278/* }}} */
     279static void xc_gc_expires_one(xc_cache_t *cache, zend_ulong gc_interval, cache_apply_dmz_func_t apply_func TSRMLS_DC) /* {{{ */
     280{
     281    fprintf(stderr, "interval %d, %d %d\n", XG(request_time), cache->last_gc_expires, gc_interval);
     282    if (XG(request_time) - cache->last_gc_expires > gc_interval) {
     283        ENTER_LOCK(cache) {
     284            if (XG(request_time) - cache->last_gc_expires > gc_interval) {
     285                cache->last_gc_expires = XG(request_time);
     286                xc_entry_apply_dmz(cache, apply_func TSRMLS_CC);
     287            }
     288        } LEAVE_LOCK(cache);
     289    }
     290}
     291/* }}} */
     292static void xc_php_gc_expires(TSRMLS_D) /* {{{ */
     293{
     294    int i, c;
     295
     296    if (!xc_php_ttl || !xc_php_gc_interval) {
     297        return;
     298    }
     299
     300    for (i = 0, c = xc_php_hcache.size; i < c; i ++) {
     301        xc_gc_expires_one(xc_php_caches[i], xc_php_gc_interval, xc_gc_php_entry_expires_dmz TSRMLS_CC);
     302    }
     303}
     304/* }}} */
     305static void xc_var_gc_expires(TSRMLS_D) /* {{{ */
     306{
     307    int i, c;
     308
     309    if (!xc_var_gc_interval) {
     310        return;
     311    }
     312
     313    for (i = 0, c = xc_var_hcache.size; i < c; i ++) {
     314        xc_gc_expires_one(xc_var_caches[i], xc_var_gc_interval, xc_gc_var_entry_expires_dmz TSRMLS_CC);
     315    }
     316}
     317/* }}} */
     318
     319static XC_CACHE_APPLY_FUNC(xc_gc_delete_dmz) /* {{{ */
     320{
     321    xc_entry_t *p, **pp;
     322
     323    pp = &cache->deletes;
     324    for (p = *pp; p; p = p->next) {
     325        if (XG(request_time) - p->dtime > 3600) {
     326            p->refcount = 0;
     327            /* issue warning here */
     328        }
     329        if (p->refcount == 0) {
     330            *pp = p->next;
     331            cache->deletes_count --;
     332            xc_entry_free_dmz(p);
     333        }
     334        else {
     335            pp = &(p->next);
     336        }
     337    }
     338}
     339/* }}} */
     340static XC_CACHE_APPLY_FUNC(xc_gc_deletes_one) /* {{{ */
     341{
     342    if (cache->deletes && XG(request_time) - cache->last_gc_deletes > xc_deletes_gc_interval) {
     343        ENTER_LOCK(cache) {
     344            if (cache->deletes && XG(request_time) - cache->last_gc_deletes > xc_deletes_gc_interval) {
     345                xc_gc_delete_dmz(cache TSRMLS_CC);
     346            }
     347        } LEAVE_LOCK(cache);
     348    }
     349}
     350/* }}} */
     351static void xc_gc_deletes(TSRMLS_D) /* {{{ */
     352{
     353    int i, c;
     354
     355    for (i = 0, c = xc_php_hcache.size; i < c; i ++) {
     356        xc_gc_deletes_one(xc_php_caches[i] TSRMLS_CC);
     357    }
     358
     359    for (i = 0, c = xc_var_hcache.size; i < c; i ++) {
     360        xc_gc_deletes_one(xc_var_caches[i] TSRMLS_CC);
     361    }
     362}
     363/* }}} */
     364
    221365/* helper functions for user functions */
    222366static void xc_fillinfo_dmz(xc_cache_t *cache, zval *return_value TSRMLS_DC) /* {{{ */
     
    236380    add_assoc_long_ex(return_value, ZEND_STRS("ooms"),      cache->ooms);
    237381
    238     add_assoc_long_ex(return_value, ZEND_STRS("cached"), cache->entries_count);
    239     add_assoc_long_ex(return_value, ZEND_STRS("deleted"), cache->deletes_count);
     382    add_assoc_long_ex(return_value, ZEND_STRS("cached"),    cache->entries_count);
     383    add_assoc_long_ex(return_value, ZEND_STRS("deleted"),   cache->deletes_count);
    240384
    241385    MAKE_STD_ZVAL(blocks);
     
    402546}
    403547/* }}} */
    404 static void xc_entry_gc_real(xc_cache_t **caches, int size TSRMLS_DC) /* {{{ */
    405 {
    406     time_t t = XG(request_time);
    407     int i;
    408     xc_cache_t *cache;
    409     typedef xc_entry_t *xc_delete_t;
    410     xc_delete_t p, *last;
    411 
    412     for (i = 0; i < size; i ++) {
    413         cache = caches[i];
    414         ENTER_LOCK(cache) {
    415             if (cache->deletes) {
    416                 last = (xc_delete_t *) &cache->deletes;
    417                 for (p = *last; p; p = p->next) {
    418                     if (t - p->dtime > 3600) {
    419                         p->refcount = 0;
    420                         /* issue warning here */
    421                     }
    422                     if (p->refcount == 0) {
    423                         *last = p->next;
    424                         cache->deletes_count --;
    425                         xc_entry_free_dmz(p);
    426                     }
    427                     else {
    428                         last = &(p->next);
    429                     }
    430                 }
    431             }
    432         } LEAVE_LOCK(cache);
    433     }
    434 }
    435 /* }}} */
    436 static void xc_entry_gc(TSRMLS_D) /* {{{ */
    437 {
    438     xc_entry_gc_real(xc_php_caches, xc_php_hcache.size TSRMLS_CC);
    439     xc_entry_gc_real(xc_var_caches, xc_var_hcache.size TSRMLS_CC);
    440 }
    441 /* }}} */
     548
    442549static inline void xc_entry_unholds_real(xc_stack_t *holds, xc_cache_t **caches, int cachecount TSRMLS_DC) /* {{{ */
    443550{
     
    781888    }
    782889    /* }}} */
    783     xc_entry_gc(TSRMLS_C);
    784890    ENTER_LOCK(cache) { /* {{{ store/add entry */
    785891        stored_xce = xc_entry_store_dmz(&xce TSRMLS_CC);
     
    9871093    xc_cache_t **caches = NULL, *cache;
    9881094    xc_mem_t *mem;
     1095    time_t now = time(NULL);
    9891096    int i;
    9901097    xc_memsize_t memsize;
     
    10171124        cache->mem     = mem;
    10181125        cache->cacheid = i;
     1126        cache->last_gc_deletes = now;
     1127        cache->last_gc_expires = now;
    10191128        caches[i] = cache;
    10201129    }
     
    11401249{
    11411250    xc_entry_unholds(TSRMLS_C);
     1251    xc_php_gc_expires(TSRMLS_C);
     1252    xc_var_gc_expires(TSRMLS_C);
     1253    xc_gc_deletes(TSRMLS_C);
    11421254#ifdef HAVE_XCACHE_COVERAGER
    11431255    xc_coverager_request_shutdown(TSRMLS_C);
     
    13451457                    }
    13461458                } LEAVE_LOCK(cache);
    1347                 xc_entry_gc(TSRMLS_C);
     1459                xc_gc_deletes(TSRMLS_C);
    13481460            }
    13491461            break;
     
    14171529}
    14181530/* }}} */
    1419 #define TIME_MAX (sizeof(time_t) == sizeof(long) ? LONG_MAX : INT_MAX)
    14201531/* {{{ proto mixed xcache_get(string name)
    14211532   Get cached data by specified name */
     
    14351546        stored_xce = xc_entry_find_dmz(&xce TSRMLS_CC);
    14361547        if (stored_xce) {
    1437             if (XG(request_time) <= stored_xce->data.var->etime) {
     1548            if (XG(request_time) <= stored_xce->ctime + stored_xce->ttl) {
    14381549                xc_processor_restore_zval(return_value, stored_xce->data.var->value TSRMLS_CC);
    14391550                /* return */
     
    14571568    zval *name;
    14581569    zval *value;
    1459     long ttl = 0;
    1460 
    1461     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|l", &name, &value, &ttl) == FAILURE) {
     1570
     1571    xce.ttl = XG(var_ttl);
     1572    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|l", &name, &value, &xce.ttl) == FAILURE) {
    14621573        return;
    14631574    }
     1575
     1576    /* max ttl */
     1577    if (xc_var_maxttl && (!xce.ttl || xce.ttl > xc_var_maxttl)) {
     1578        xce.ttl = xc_var_maxttl;
     1579    }
     1580
    14641581    xce.data.var = &var;
    14651582    xc_entry_init_key_var(&xce, name TSRMLS_CC);
     
    14711588        }
    14721589        var.value = value;
    1473         var.etime = ttl ? XG(request_time) + ttl : TIME_MAX;
    14741590        RETVAL_BOOL(xc_entry_store_dmz(&xce TSRMLS_CC) != NULL ? 1 : 0);
    14751591    } LEAVE_LOCK(xce.cache);
     
    14931609        stored_xce = xc_entry_find_dmz(&xce TSRMLS_CC);
    14941610        if (stored_xce) {
    1495             if (XG(request_time) <= stored_xce->data.var->etime) {
     1611            if (VAR_ENTRY_EXPIRED(stored_xce)) {
    14961612                RETVAL_TRUE;
    14971613                /* return */
     
    15391655    zval *name;
    15401656    long count = 1;
    1541     long ttl = 0;
    15421657    long value = 0;
    15431658    zval oldzval;
    15441659
    1545     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|ll", &name, &count, &ttl) == FAILURE) {
     1660    xce.ttl = XG(var_ttl);
     1661    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|ll", &name, &count, &xce.ttl) == FAILURE) {
    15461662        return;
    15471663    }
     1664
     1665    /* max ttl */
     1666    if (xc_var_maxttl && (!xce.ttl || xce.ttl > xc_var_maxttl)) {
     1667        xce.ttl = xc_var_maxttl;
     1668    }
     1669
    15481670    xce.data.var = &var;
    15491671    xc_entry_init_key_var(&xce, name TSRMLS_CC);
     
    15551677            fprintf(stderr, "incdec: gotxce %s\n", xce.name.str.val);
    15561678#endif
    1557             stored_var = stored_xce->data.var;
    15581679            /* timeout */
    1559             if (XG(request_time) > stored_var->etime) {
     1680            if (VAR_ENTRY_EXPIRED(stored_xce)) {
    15601681#ifdef DEBUG
    15611682                fprintf(stderr, "incdec: expired\n");
     
    15661687            else {
    15671688                /* do it in place */
     1689                stored_var = stored_xce->data.var;
    15681690                if (Z_TYPE_P(stored_var->value) == IS_LONG) {
     1691                    stored_xce->ctime = XG(request_time);
     1692                    stored_xce->ttl   = xce.ttl;
    15691693#ifdef DEBUG
    15701694                    fprintf(stderr, "incdec: islong\n");
     
    15741698                    RETVAL_LONG(value);
    15751699                    Z_LVAL_P(stored_var->value) = value;
    1576                     break;
     1700                    break; /* leave lock */
    15771701                }
    15781702                else {
     
    15961720        RETVAL_LONG(value);
    15971721        var.value = return_value;
    1598         var.etime = ttl ? XG(request_time) + ttl : TIME_MAX;
     1722
    15991723        if (stored_xce) {
    16001724            xce.atime = stored_xce->atime;
     
    19132037}
    19142038
    1915 #ifdef ZEND_ENGINE_2
    1916 #define OnUpdateInt OnUpdateLong
     2039#ifndef ZEND_ENGINE_2
     2040#define OnUpdateLong OnUpdateInt
    19172041#endif
    19182042
     
    19322056    STD_PHP_INI_BOOLEAN("xcache.optimizer",              "0", PHP_INI_ALL,    OnUpdateBool,        optimizer,         zend_xcache_globals, xcache_globals)
    19332057#endif
     2058    STD_PHP_INI_BOOLEAN("xcache.var_ttl",                "0", PHP_INI_ALL,    OnUpdateLong,        var_ttl,   zend_xcache_globals, xcache_globals)
    19342059#ifdef HAVE_XCACHE_COVERAGER
    19352060    PHP_INI_ENTRY1     ("xcache.coveragedump_directory", "/tmp/pcov/", PHP_INI_SYSTEM, xc_OnUpdateString,   &xc_coveragedump_dir)
     
    19922117    php_info_print_table_start();
    19932118    php_info_print_table_header(2, "Directive ", "Value");
    1994     xc_config_long_disp("xcache.size",       "0");
    1995     xc_config_hash_disp("xcache.count",      "1");
    1996     xc_config_hash_disp("xcache.slots",     "8K");
    1997 
    1998     xc_config_long_disp("xcache.var_size",   "0");
    1999     xc_config_hash_disp("xcache.var_count",  "1");
    2000     xc_config_hash_disp("xcache.var_slots", "8K");
     2119    xc_config_long_disp("xcache.size",        "0");
     2120    xc_config_hash_disp("xcache.count",       "1");
     2121    xc_config_hash_disp("xcache.slots",      "8K");
     2122    xc_config_hash_disp("xcache.ttl",         "0");
     2123    xc_config_hash_disp("xcache.gc_interval", "0");
     2124
     2125    xc_config_long_disp("xcache.var_size",           "0");
     2126    xc_config_hash_disp("xcache.var_count",          "1");
     2127    xc_config_hash_disp("xcache.var_slots",         "8K");
     2128    xc_config_hash_disp("xcache.var_maxttl",         "0");
     2129    xc_config_hash_disp("xcache.var_gc_interval",  "300");
    20012130    php_info_print_table_end();
    20022131
     
    20972226    }
    20982227
    2099     xc_config_long(&xc_php_size,   "xcache.size",       "0");
    2100     xc_config_hash(&xc_php_hcache, "xcache.count",      "1");
    2101     xc_config_hash(&xc_php_hentry, "xcache.slots",     "8K");
    2102 
    2103     xc_config_long(&xc_var_size,   "xcache.var_size",   "0");
    2104     xc_config_hash(&xc_var_hcache, "xcache.var_count",  "1");
    2105     xc_config_hash(&xc_var_hentry, "xcache.var_slots", "8K");
     2228    xc_config_long(&xc_php_size,       "xcache.size",        "0");
     2229    xc_config_hash(&xc_php_hcache,     "xcache.count",       "1");
     2230    xc_config_hash(&xc_php_hentry,     "xcache.slots",      "8K");
     2231    xc_config_long(&xc_php_ttl,        "xcache.ttl",         "0");
     2232    xc_config_long(&xc_php_gc_interval, "xcache.gc_interval", "0");
     2233
     2234    xc_config_long(&xc_var_size,       "xcache.var_size",          "0");
     2235    xc_config_hash(&xc_var_hcache,     "xcache.var_count",         "1");
     2236    xc_config_hash(&xc_var_hentry,     "xcache.var_slots",        "8K");
     2237    xc_config_long(&xc_var_maxttl,     "xcache.var_maxttl",        "0");
     2238    xc_config_long(&xc_var_gc_interval, "xcache.var_gc_interval", "120");
    21062239
    21072240    if (xc_php_size <= 0) {
Note: See TracChangeset for help on using the changeset viewer.