Changeset 311 in svn for trunk/xcache.c


Ignore:
Timestamp:
2006-12-09T17:27:03+01:00 (9 years ago)
Author:
Xuefer
Message:

restruct cached compile, add md5 table to recognize and merge file with same content

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/xcache.c

    r307 r311  
    106106/* any function in *_dmz is only safe be called within locked(single thread) area */
    107107
     108static void xc_php_add_dmz(xc_entry_data_php_t *php) /* {{{ */
     109{
     110    xc_entry_data_php_t **head = &(php->cache->phps[php->hvalue]);
     111    php->next = *head;
     112    *head = php;
     113    php->cache->phps_count ++;
     114}
     115/* }}} */
     116static xc_entry_data_php_t *xc_php_store_dmz(xc_entry_data_php_t *php TSRMLS_DC) /* {{{ */
     117{
     118    xc_entry_data_php_t *stored_php;
     119
     120    php->hits     = 0;
     121    php->refcount = 0;
     122    stored_php = xc_processor_store_xc_entry_data_php_t(php TSRMLS_CC);
     123    if (stored_php) {
     124        xc_php_add_dmz(stored_php);
     125        return stored_php;
     126    }
     127    else {
     128        php->cache->ooms ++;
     129        return NULL;
     130    }
     131}
     132/* }}} */
     133static xc_entry_data_php_t *xc_php_find_dmz(xc_entry_data_php_t *php TSRMLS_DC) /* {{{ */
     134{
     135    xc_entry_data_php_t *p;
     136    for (p = php->cache->phps[php->hvalue]; p; p = p->next) {
     137        if (memcmp(php->md5, p->md5, sizeof(php->md5)) == 0) {
     138            p->hits ++;
     139            return p;
     140        }
     141    }
     142    return NULL;
     143}
     144/* }}} */
     145static void xc_php_free_dmz(xc_entry_data_php_t *php) /* {{{ */
     146{
     147    php->cache->mem->handlers->free(php->cache->mem, (xc_entry_data_php_t *)php);
     148}
     149/* }}} */
     150static void xc_php_remove_dmz(xc_entry_data_php_t *php) /* {{{ */
     151{
     152    if (-- php->refcount == 0) {
     153        xc_entry_data_php_t **pp = &(php->cache->phps[php->hvalue]);
     154        xc_entry_data_php_t *p;
     155        for (p = *pp; p; pp = &(p->next), p = p->next) {
     156            if (memcmp(php->md5, p->md5, sizeof(php->md5)) == 0) {
     157                /* unlink */
     158                *pp = p->next;
     159                xc_php_free_dmz(php);
     160                return;
     161            }
     162        }
     163        assert(0);
     164    }
     165}
     166/* }}} */
     167
    108168static inline int xc_entry_equal_dmz(xc_entry_t *a, xc_entry_t *b) /* {{{ */
    109169{
     
    117177#ifdef HAVE_INODE
    118178            do {
    119                 xc_entry_data_php_t *ap = a->data.php;
    120                 xc_entry_data_php_t *bp = b->data.php;
    121                 if (ap->inode) {
    122                     return ap->inode == bp->inode
    123                         && ap->device == bp->device;
     179                if (a->inode) {
     180                    return a->inode == b->inode
     181                        && a->device == b->device;
    124182                }
    125183            } while(0);
     
    150208}
    151209/* }}} */
    152 static void xc_entry_free_real_dmz(volatile xc_entry_t *xce) /* {{{ */
    153 {
    154     xce->cache->mem->handlers->free(xce->cache->mem, (xc_entry_t *)xce);
    155 }
    156 /* }}} */
    157210static void xc_entry_add_dmz(xc_entry_t *xce) /* {{{ */
    158211{
     
    179232        return NULL;
    180233    }
     234}
     235/* }}} */
     236static void xc_entry_free_real_dmz(volatile xc_entry_t *xce) /* {{{ */
     237{
     238    if (xce->type == XC_TYPE_PHP) {
     239        xc_php_remove_dmz(xce->data.php);
     240    }
     241    xce->cache->mem->handlers->free(xce->cache->mem, (xc_entry_t *)xce);
    181242}
    182243/* }}} */
     
    216277    for (p = xce->cache->entries[xce->hvalue]; p; p = p->next) {
    217278        if (xc_entry_equal_dmz(xce, p)) {
    218             if (p->type == XC_TYPE_VAR || /* PHP */ p->data.php->mtime == xce->data.php->mtime) {
     279            if (p->type == XC_TYPE_VAR || /* PHP */ p->mtime == xce->mtime) {
    219280                p->hits ++;
    220281                p->atime = XG(request_time);
     
    474535            add_assoc_long_ex(ei, ZEND_STRS("sourcesize"),    php->sourcesize);
    475536#ifdef HAVE_INODE
    476             add_assoc_long_ex(ei, ZEND_STRS("device"),        php->device);
    477             add_assoc_long_ex(ei, ZEND_STRS("inode"),         php->inode);
    478 #endif
    479             add_assoc_long_ex(ei, ZEND_STRS("mtime"),         php->mtime);
     537            add_assoc_long_ex(ei, ZEND_STRS("device"),        entry->device);
     538            add_assoc_long_ex(ei, ZEND_STRS("inode"),         entry->inode);
     539#endif
     540            add_assoc_long_ex(ei, ZEND_STRS("mtime"),         entry->mtime);
    480541
    481542#ifdef HAVE_XCACHE_CONSTANT
     
    644705        if (VCWD_STAT(filepath, pbuf) == 0) {
    645706            free_alloca(paths);
    646             return 0;
     707            return FAILURE;
    647708        }
    648709    }
     
    650711    free_alloca(paths);
    651712
    652     return 1;
     713    return SUCCESS;
    653714}
    654715/* }}} */
     
    656717#define HASH(i) (i)
    657718#define HASH_USTR_L(t, s, l) HASH(zend_u_inline_hash_func(t, s, (l + 1) * sizeof(UChar)))
    658 #define HASH_STR_L(s, l) HASH(zend_inline_hash_func(s, l + 1))
     719#define HASH_STR_S(s, l) HASH(zend_inline_hash_func(s, l))
     720#define HASH_STR_L(s, l) HASH_STR_S(s, l + 1)
    659721#define HASH_STR(s) HASH_STR_L(s, strlen(s) + 1)
    660722#define HASH_NUM(n) HASH(n)
     
    669731{
    670732#ifdef HAVE_INODE
    671     if (xce->data.php->inode) {
    672         return HASH(xce->data.php->device + xce->data.php->inode);
     733    if (xce->inode) {
     734        return HASH(xce->device + xce->inode);
    673735    }
    674736#endif
     
    685747
    686748    if (!filename || !SG(request_info).path_translated) {
    687         return 0;
     749        return FAILURE;
    688750    }
    689751
     
    703765        if (IS_ABSOLUTE_PATH(filename, strlen(filename))) {
    704766            if (VCWD_STAT(filename, pbuf) != 0) {
    705                 return 0;
     767                return FAILURE;
    706768            }
    707769            goto stat_done;
     
    719781
    720782            if (VCWD_STAT(filename, pbuf) != 0) {
    721                 return 0;
     783                return FAILURE;
    722784            }
    723785            goto stat_done;
     
    726788
    727789        /* use include_path */
    728         if (xc_stat(filename, PG(include_path), pbuf TSRMLS_CC) != 0) {   
    729             return 0;
     790        if (xc_stat(filename, PG(include_path), pbuf TSRMLS_CC) != SUCCESS) {
     791            return FAILURE;
    730792        }
    731793
     
    734796stat_done:
    735797        if (XG(request_time) - pbuf->st_mtime < 2 && !xc_test) {
    736             return 0;
    737         }
    738 
    739         php->mtime        = pbuf->st_mtime;
     798            return FAILURE;
     799        }
     800
     801        xce->mtime        = pbuf->st_mtime;
    740802#ifdef HAVE_INODE
    741         php->device       = pbuf->st_dev;
    742         php->inode        = pbuf->st_ino;
     803        xce->device       = pbuf->st_dev;
     804        xce->inode        = pbuf->st_ino;
    743805#endif
    744806        php->sourcesize   = pbuf->st_size;
    745807    }
    746808    else { /* XG(inode) */
    747         php->mtime        = 0;
     809        xce->mtime        = 0;
    748810#ifdef HAVE_INODE
    749         php->device       = 0;
    750         php->inode        = 0;
     811        xce->device       = 0;
     812        xce->inode        = 0;
    751813#endif
    752814        php->sourcesize   = 0;
     
    754816
    755817#ifdef HAVE_INODE
    756     if (!php->inode)
     818    if (!xce->inode)
    757819#endif
    758820    {
     
    760822        filename = expand_filepath(filename, opened_path_buffer TSRMLS_CC);
    761823        if (filename == NULL) {
    762             return 0;
     824            return FAILURE;
    763825        }
    764826    }
     
    775837
    776838    xce->type = XC_TYPE_PHP;
    777     return 1;
     839    return SUCCESS;
     840}
     841/* }}} */
     842static inline xc_hash_value_t xc_php_hash_md5(xc_entry_data_php_t *php TSRMLS_DC) /* {{{ */
     843{
     844    return HASH_STR_S(php->md5, sizeof(php->md5));
     845}
     846/* }}} */
     847static int xc_entry_init_key_php_md5(xc_entry_data_php_t *php, xc_entry_t *xce TSRMLS_DC) /* {{{ */
     848{
     849    unsigned char   buf[1024];
     850    PHP_MD5_CTX     context;
     851    int             n;
     852    php_stream     *stream;
     853    xc_hash_value_t hv;
     854
     855    stream = php_stream_open_wrapper(xce->name.str.val, "rb", REPORT_ERRORS | ENFORCE_SAFE_MODE, NULL);
     856    if (!stream) {
     857        return FAILURE;
     858    }
     859
     860    PHP_MD5Init(&context);
     861    while ((n = php_stream_read(stream, (char *) buf, sizeof(buf))) > 0) {
     862        PHP_MD5Update(&context, buf, n);
     863    }
     864    PHP_MD5Final((unsigned char *) php->md5, &context);
     865
     866    php_stream_close(stream);
     867
     868    if (n < 0) {
     869        return FAILURE;
     870    }
     871
     872    hv = xc_php_hash_md5(php TSRMLS_CC);
     873    php->cache  = xce->cache;
     874    php->hvalue = (hv & php->cache->hphp->mask);
     875#ifdef DEBUG
     876    {
     877        char md5str[33];
     878        make_digest(md5str, (unsigned char *) php->md5);
     879        TRACE("md5 %s", md5str);
     880    }
     881#endif
     882
     883    return SUCCESS;
    778884}
    779885/* }}} */
     
    805911}
    806912/* }}} */
    807 static zend_op_array *xc_compile_file(zend_file_handle *h, int type TSRMLS_DC) /* {{{ */
    808 {
    809     xc_sandbox_t sandbox;
     913static void xc_free_php(xc_entry_data_php_t *php TSRMLS_DC) /* {{{ */
     914{
     915#define X_FREE(var) do {\
     916    if (php->var) { \
     917        efree(php->var); \
     918    } \
     919} while (0)
     920
     921#ifdef ZEND_ENGINE_2_1
     922    X_FREE(autoglobals);
     923#endif
     924    X_FREE(classinfos);
     925    X_FREE(funcinfos);
     926#ifdef HAVE_XCACHE_CONSTANT
     927    X_FREE(constinfos);
     928#endif
     929#undef X_FREE
     930}
     931/* }}} */
     932static zend_op_array *xc_compile_php(xc_entry_data_php_t *php, zend_file_handle *h, int type TSRMLS_DC) /* {{{ */
     933{
    810934    zend_op_array *op_array;
    811     xc_entry_t xce, *stored_xce;
    812     xc_entry_data_php_t php;
    813     xc_cache_t *cache;
    814     zend_bool clogged = 0;
    815     zend_bool catched = 0;
    816     char *filename;
    817     char opened_path_buffer[MAXPATHLEN];
    818935    int old_constinfo_cnt, old_funcinfo_cnt, old_classinfo_cnt;
    819936    int i;
    820 
    821     if (!xc_initized) {
    822         assert(0);
    823     }
    824 
    825     if (!XG(cacher)) {
    826         op_array = origin_compile_file(h, type TSRMLS_CC);
    827 #ifdef HAVE_XCACHE_OPTIMIZER
    828         if (XG(optimizer)) {
    829             xc_optimize(op_array TSRMLS_CC);
    830         }
    831 #endif
    832         return op_array;
    833     }
    834 
    835     /* {{{ prepare key
    836      * include_once() and require_once() gives us opened_path
    837      * however, include() and require() non-absolute path which break
    838      * included_files, and may confuse with (include|require)_once
    839      * -- Xuefer
    840      */
    841 
    842     filename = h->opened_path ? h->opened_path : h->filename;
    843     xce.data.php = &php;
    844     if (!xc_entry_init_key_php(&xce, filename, opened_path_buffer TSRMLS_CC)) {
    845         return origin_compile_file(h, type TSRMLS_CC);
    846     }
    847     cache = xce.cache;
    848     /* }}} */
    849     /* {{{ restore */
    850     /* stale precheck */
    851     if (cache->compiling) {
    852         cache->clogs ++; /* is it safe here? */
    853         return origin_compile_file(h, type TSRMLS_CC);
    854     }
    855 
    856     stored_xce = NULL;
    857     op_array = NULL;
    858     ENTER_LOCK_EX(cache) {
    859         /* clogged */
    860         if (cache->compiling) {
    861             cache->clogs ++;
    862             op_array = NULL;
    863             clogged = 1;
    864             break;
    865         }
    866 
    867         stored_xce = xc_entry_find_dmz(&xce TSRMLS_CC);
    868         /* found */
    869         if (stored_xce) {
    870             TRACE("found %s, catch it", stored_xce->name.str.val);
    871             xc_entry_hold_php_dmz(stored_xce TSRMLS_CC);
    872             cache->hits ++;
    873             break;
    874         }
    875 
    876         cache->compiling = XG(request_time);
    877         cache->misses ++;
    878     } LEAVE_LOCK_EX(cache);
    879 
    880     if (catched) {
    881         cache->compiling = 0;
    882         zend_bailout();
    883     }
    884 
    885     /* found */
    886     if (stored_xce) {
    887         goto restore;
    888     }
    889 
    890     /* clogged */
    891     if (clogged) {
    892         return origin_compile_file(h, type TSRMLS_CC);
    893     }
    894     /* }}} */
     937    zend_bool catched = 0;
    895938
    896939    /* {{{ compile */
    897     TRACE("compiling %s", filename);
    898 
    899     /* make compile inside sandbox */
    900     xc_sandbox_init(&sandbox, filename TSRMLS_CC);
     940    TRACE("compiling %s", h->opened_path ? h->opened_path : h->filename);
    901941
    902942    old_classinfo_cnt = zend_hash_num_elements(CG(class_table));
     
    915955
    916956    if (op_array == NULL) {
    917         goto err_oparray;
    918     }
    919 
    920     filename = h->opened_path ? h->opened_path : h->filename;
    921     /* none-inode enabled entry hash/compare on name
    922      * do not update to its name to real pathname
    923      */
    924 #ifdef HAVE_INODE
    925     if (xce.data.php->inode)
    926     {
    927         if (xce.name.str.val != filename) {
    928             xce.name.str.val = filename;
    929             xce.name.str.len = strlen(filename);
    930         }
    931     }
    932 #endif
     957        goto err_op_array;
     958    }
    933959
    934960#ifdef HAVE_XCACHE_OPTIMIZER
     
    939965    /* }}} */
    940966    /* {{{ prepare */
    941     php.op_array      = op_array;
     967    php->op_array      = op_array;
    942968
    943969#ifdef HAVE_XCACHE_CONSTANT
    944     php.constinfo_cnt  = zend_hash_num_elements(EG(zend_constants)) - old_constinfo_cnt;
    945 #endif
    946     php.funcinfo_cnt   = zend_hash_num_elements(CG(function_table)) - old_funcinfo_cnt;
    947     php.classinfo_cnt  = zend_hash_num_elements(CG(class_table))    - old_classinfo_cnt;
     970    php->constinfo_cnt  = zend_hash_num_elements(EG(zend_constants)) - old_constinfo_cnt;
     971#endif
     972    php->funcinfo_cnt   = zend_hash_num_elements(CG(function_table)) - old_funcinfo_cnt;
     973    php->classinfo_cnt  = zend_hash_num_elements(CG(class_table))    - old_classinfo_cnt;
    948974#ifdef ZEND_ENGINE_2_1
    949     /* {{{ count php.autoglobal_cnt */ {
     975    /* {{{ count php->autoglobal_cnt */ {
    950976        Bucket *b;
    951977
    952         php.autoglobal_cnt = 0;
     978        php->autoglobal_cnt = 0;
    953979        for (b = CG(auto_globals)->pListHead; b != NULL; b = b->pListNext) {
    954980            zend_auto_global *auto_global = (zend_auto_global *) b->pData;
    955981            /* check if actived */
    956982            if (auto_global->auto_global_callback && !auto_global->armed) {
    957                 php.autoglobal_cnt ++;
     983                php->autoglobal_cnt ++;
    958984            }
    959985        }
     
    963989
    964990#define X_ALLOC_N(var, cnt) do {     \
    965     if (php.cnt) {                   \
    966         ECALLOC_N(php.var, php.cnt); \
    967         if (!php.var) {              \
    968             goto err_##var;          \
     991    if (php->cnt) {                  \
     992        ECALLOC_N(php->var, php->cnt); \
     993        if (!php->var) {             \
     994            goto err_alloc;          \
    969995        }                            \
    970996    }                                \
    971997    else {                           \
    972         php.var = NULL;              \
     998        php->var = NULL;             \
    973999    }                                \
    9741000} while (0)
     
    9901016#define COPY_H(vartype, var, cnt, name, datatype) do {        \
    9911017    for (i = 0; b; i ++, b = b->pListNext) {                  \
    992         vartype *data = &php.var[i];                          \
     1018        vartype *data = &php->var[i];                         \
    9931019                                                              \
    9941020        if (i < old_##cnt) {                                  \
     
    9961022        }                                                     \
    9971023                                                              \
    998         assert(i < old_##cnt + php.cnt);                      \
     1024        assert(i < old_##cnt + php->cnt);                     \
    9991025        assert(b->pData);                                     \
    10001026        memcpy(&data->name, b->pData, sizeof(datatype));      \
    10011027        UNISW(NOTHING, data->type = b->key.type;)             \
    10021028        if (UNISW(1, b->key.type == IS_STRING)) {             \
    1003             ZSTR_S(data->key)      = BUCKET_KEY_S(b);          \
     1029            ZSTR_S(data->key)      = BUCKET_KEY_S(b);         \
    10041030        }                                                     \
    10051031        else {                                                \
     
    10271053            /* check if actived */
    10281054            if (auto_global->auto_global_callback && !auto_global->armed) {
    1029                 xc_autoglobal_t *data = &php.autoglobals[i];
    1030 
    1031                 assert(i < php.autoglobal_cnt);
     1055                xc_autoglobal_t *data = &php->autoglobals[i];
     1056
     1057                assert(i < php->autoglobal_cnt);
    10321058                i ++;
    10331059                UNISW(NOTHING, data->type = b->key.type;)
     
    10451071    /* }}} */
    10461072    /* {{{ find inherited classes that should be early-binding */
    1047     php.have_early_binding = 0;
    1048     for (i = 0; i < php.classinfo_cnt; i ++) {
    1049         php.classinfos[i].oplineno = -1;
    1050     }
    1051 
    1052     xc_undo_pass_two(php.op_array TSRMLS_CC);
    1053     xc_foreach_early_binding_class(php.op_array, xc_cache_early_binding_class_cb, (void *) &php TSRMLS_CC);
    1054     xc_redo_pass_two(php.op_array TSRMLS_CC);
     1073    php->have_early_binding = 0;
     1074    for (i = 0; i < php->classinfo_cnt; i ++) {
     1075        php->classinfos[i].oplineno = -1;
     1076    }
     1077
     1078    xc_undo_pass_two(php->op_array TSRMLS_CC);
     1079    xc_foreach_early_binding_class(php->op_array, xc_cache_early_binding_class_cb, (void *) &php TSRMLS_CC);
     1080    xc_redo_pass_two(php->op_array TSRMLS_CC);
    10551081    /* }}} */
    1056 #ifdef SHOW_DPRINT
    1057     xc_dprint(&xce, 0 TSRMLS_CC);
    1058 #endif
    1059     ENTER_LOCK_EX(cache) { /* {{{ store/add entry */
    1060         stored_xce = xc_entry_store_dmz(&xce TSRMLS_CC);
    1061     } LEAVE_LOCK_EX(cache);
    1062     /* }}} */
    1063     TRACE("%s", "stored");
    1064 
    1065 #define X_FREE(var) \
    1066     if (xce.data.php->var) { \
    1067         efree(xce.data.php->var); \
    1068     } \
    1069 err_##var:
    1070 
    1071 #ifdef ZEND_ENGINE_2_1
    1072     X_FREE(autoglobals)
    1073 #endif
    1074     X_FREE(classinfos)
    1075     X_FREE(funcinfos)
    1076 #ifdef HAVE_XCACHE_CONSTANT
    1077     X_FREE(constinfos)
    1078 #endif
    1079 #undef X_FREE
    1080 
    1081 err_oparray:
     1082
     1083    return op_array;
     1084
     1085err_alloc:
     1086    xc_free_php(php TSRMLS_CC);
     1087
    10821088err_bailout:
    1083 
    1084     if (xc_test && stored_xce) {
    1085         /* free it, no install. restore now */
    1086         xc_sandbox_free(&sandbox, 0 TSRMLS_CC);
    1087     }
    1088     else if (!op_array) {
    1089         /* failed to compile free it, no install */
    1090         xc_sandbox_free(&sandbox, 0 TSRMLS_CC);
    1091     }
    1092     else {
    1093         CG(active_op_array) = op_array;
    1094         xc_sandbox_free(&sandbox, 1 TSRMLS_CC);
    1095     }
    1096 
    1097     ENTER_LOCK(cache) {
    1098         cache->compiling = 0;
    1099     } LEAVE_LOCK(cache);
     1089err_op_array:
     1090
    11001091    if (catched) {
    11011092        zend_bailout();
    11021093    }
    1103     if (xc_test && stored_xce) {
    1104 #ifdef ZEND_ENGINE_2
    1105         destroy_op_array(op_array TSRMLS_CC);
    1106 #else
    1107         destroy_op_array(op_array);
    1108 #endif
    1109         efree(op_array);
    1110         h = NULL;
    1111         goto restore;
    1112     }
     1094
    11131095    return op_array;
    1114 
    1115 restore:
     1096}
     1097/* }}} */
     1098static zend_op_array *xc_compile_restore(xc_entry_t *stored_xce, zend_file_handle *h TSRMLS_DC) /* {{{ */
     1099{
     1100    zend_op_array *op_array;
     1101    xc_entry_t xce;
     1102    xc_entry_data_php_t php;
     1103    zend_bool catched;
     1104
    11161105    CG(in_compilation)    = 1;
    11171106    CG(compiled_filename) = stored_xce->name.str.val;
    11181107    CG(zend_lineno)       = 0;
    11191108    TRACE("restoring %s", stored_xce->name.str.val);
    1120     xc_processor_restore_xc_entry_t(&xce, stored_xce, xc_readonly_protection TSRMLS_CC);
     1109    xc_processor_restore_xc_entry_t(&xce, stored_xce TSRMLS_CC);
     1110    xc_processor_restore_xc_entry_data_php_t(&php, xce.data.php, xc_readonly_protection TSRMLS_CC);
     1111    xce.data.php = &php;
    11211112#ifdef SHOW_DPRINT
    11221113    xc_dprint(&xce, 0 TSRMLS_CC);
     
    11301121    } zend_end_try();
    11311122
    1132 #define X_FREE(var) \
    1133     if (xce.data.php->var) { \
    1134         efree(xce.data.php->var); \
    1135     }
    1136 #ifdef ZEND_ENGINE_2_1
    1137     X_FREE(autoglobals)
    1138 #endif
    1139     X_FREE(classinfos)
    1140     X_FREE(funcinfos)
    1141 #ifdef HAVE_XCACHE_CONSTANT
    1142     X_FREE(constinfos)
    1143 #endif
    1144 #undef X_FREE
    1145     efree(xce.data.php);
     1123    xc_free_php(&php TSRMLS_CC);
    11461124
    11471125    if (catched) {
     
    11511129    CG(compiled_filename) = NULL;
    11521130    TRACE("restored  %s", stored_xce->name.str.val);
     1131    return op_array;
     1132}
     1133/* }}} */
     1134static zend_op_array *xc_compile_file(zend_file_handle *h, int type TSRMLS_DC) /* {{{ */
     1135{
     1136    zend_op_array *op_array;
     1137    xc_entry_t xce, *stored_xce;
     1138    xc_entry_data_php_t php, *stored_php;
     1139    xc_cache_t *cache;
     1140    zend_bool gaveup = 0;
     1141    zend_bool catched = 0;
     1142    zend_bool cached_php;
     1143    char *filename;
     1144    char opened_path_buffer[MAXPATHLEN];
     1145    xc_sandbox_t sandbox;
     1146
     1147    assert(xc_initized);
     1148
     1149    if (!XG(cacher)) {
     1150        op_array = origin_compile_file(h, type TSRMLS_CC);
     1151#ifdef HAVE_XCACHE_OPTIMIZER
     1152        if (XG(optimizer)) {
     1153            xc_optimize(op_array TSRMLS_CC);
     1154        }
     1155#endif
     1156        return op_array;
     1157    }
     1158
     1159    /* {{{ entry_init_key */
     1160    filename = h->opened_path ? h->opened_path : h->filename;
     1161    xce.data.php = &php;
     1162    if (xc_entry_init_key_php(&xce, filename, opened_path_buffer TSRMLS_CC) != SUCCESS) {
     1163        return origin_compile_file(h, type TSRMLS_CC);
     1164    }
     1165    cache = xce.cache;
     1166    /* }}} */
     1167
     1168    /* stale clogs precheck */
     1169    if (cache->compiling) {
     1170        cache->clogs ++;
     1171        return origin_compile_file(h, type TSRMLS_CC);
     1172    }
     1173    /* {{{ entry_lookup/hit/md5_init/php_lookup */
     1174    stored_xce = NULL;
     1175    stored_php = NULL;
     1176    ENTER_LOCK_EX(cache) {
     1177        stored_xce = xc_entry_find_dmz(&xce TSRMLS_CC);
     1178        if (stored_xce) {
     1179            cache->hits ++;
     1180
     1181            TRACE("hit %s, holding", stored_xce->name.str.val);
     1182            xc_entry_hold_php_dmz(stored_xce TSRMLS_CC);
     1183        }
     1184        else {
     1185            cache->misses ++;
     1186            TRACE("miss %s", xce.name.str.val);
     1187
     1188            if (xc_entry_init_key_php_md5(&php, &xce TSRMLS_CC) != SUCCESS) {
     1189                gaveup = 1;
     1190                break;
     1191            }
     1192
     1193            stored_php = xc_php_find_dmz(&php TSRMLS_CC);
     1194
     1195            /* miss but compiling */
     1196            if (!stored_php) {
     1197                if (cache->compiling) {
     1198                    TRACE("%s", "miss but compiling");
     1199                    cache->clogs ++;
     1200                    gaveup = 1;
     1201                    break;
     1202                }
     1203                TRACE("%s", "php_lookup miss");
     1204            }
     1205            else {
     1206                TRACE("%s", "php_lookup hit");
     1207            }
     1208
     1209            cache->compiling = XG(request_time);
     1210        }
     1211    } LEAVE_LOCK_EX(cache);
     1212
     1213    if (catched) {
     1214        cache->compiling = 0;
     1215        zend_bailout();
     1216    }
     1217
     1218    /* hit */
     1219    if (stored_xce) {
     1220        return xc_compile_restore(stored_xce, h TSRMLS_CC);
     1221    }
     1222
     1223    /* gaveup */
     1224    if (gaveup) {
     1225        return origin_compile_file(h, type TSRMLS_CC);
     1226    }
     1227    /* }}} */
     1228    op_array = NULL;
     1229    /* {{{ compile */
     1230    if (stored_php) {
     1231        cached_php = 1;
     1232        xce.data.php = stored_php;
     1233    }
     1234    else {
     1235        cached_php = 0;
     1236
     1237        /* make compile inside sandbox */
     1238        xc_sandbox_init(&sandbox, filename TSRMLS_CC);
     1239        zend_try {
     1240            op_array = xc_compile_php(&php, h, type TSRMLS_CC);
     1241        } zend_catch {
     1242            catched = 1;
     1243        } zend_end_try();
     1244        xc_sandbox_free(&sandbox, 0 TSRMLS_CC);
     1245
     1246        if (catched) {
     1247            cache->compiling = 0;
     1248            zend_bailout();
     1249        }
     1250
     1251        xce.data.php = &php;
     1252    }
     1253    /* }}} */
     1254#ifdef HAVE_INODE
     1255    /* {{{ path name fix
     1256     * inode enabled entry hash/compare on name
     1257     * do not update to its name to real pathname
     1258     * WARNING: this code is required to be after compile
     1259     */
     1260    if (xce.inode) {
     1261        filename = h->opened_path ? h->opened_path : h->filename;
     1262        if (xce.name.str.val != filename) {
     1263            xce.name.str.val = filename;
     1264            xce.name.str.len = strlen(filename);
     1265        }
     1266    }
     1267    /* }}} */
     1268#endif
     1269#ifdef SHOW_DPRINT
     1270    xc_dprint(&xce, 0 TSRMLS_CC);
     1271#endif
     1272    stored_xce = NULL;
     1273    ENTER_LOCK_EX(cache) { /* {{{ php_store/entry_store */
     1274        /* php_store */
     1275        if (!cached_php) {
     1276            stored_php = xc_php_store_dmz(&php TSRMLS_CC);
     1277            /* error */
     1278            if (!stored_php) {
     1279                break;
     1280            }
     1281        }
     1282        /* entry_store */
     1283        stored_xce = xc_entry_store_dmz(&xce TSRMLS_CC);
     1284        if (stored_xce) {
     1285            stored_xce->data.php = stored_php;
     1286            stored_php->refcount ++;
     1287        }
     1288        else {
     1289            /* error */
     1290            xc_php_remove_dmz(stored_php);
     1291            stored_php = NULL;
     1292        }
     1293    } LEAVE_LOCK_EX(cache);
     1294    /* }}} */
     1295    TRACE("%s", stored_xce ? "stored" : "store failed");
     1296
     1297    cache->compiling = 0;
     1298    if (catched) {
     1299        zend_bailout();
     1300    }
     1301
     1302    if (stored_xce) {
     1303        if (op_array) {
     1304#ifdef ZEND_ENGINE_2
     1305            destroy_op_array(op_array TSRMLS_CC);
     1306#else
     1307            destroy_op_array(op_array);
     1308#endif
     1309            efree(op_array);
     1310            h = NULL;
     1311        }
     1312        return xc_compile_restore(stored_xce, h TSRMLS_CC);
     1313    }
    11531314    return op_array;
    11541315}
     
    12791440}
    12801441/* }}} */
    1281 static xc_cache_t **xc_cache_init(xc_shm_t *shm, xc_hash_t *hcache, xc_hash_t *hentry, xc_shmsize_t shmsize) /* {{{ */
     1442static xc_cache_t **xc_cache_init(xc_shm_t *shm, xc_hash_t *hcache, xc_hash_t *hentry, xc_hash_t *hphp, xc_shmsize_t shmsize) /* {{{ */
    12821443{
    12831444    xc_cache_t **caches = NULL, *cache;
     
    13061467        CHECK(cache          = mem->handlers->calloc(mem, 1, sizeof(xc_cache_t)), "cache OOM");
    13071468        CHECK(cache->entries = mem->handlers->calloc(mem, hentry->size, sizeof(xc_entry_t*)), "entries OOM");
     1469        if (hphp) {
     1470            CHECK(cache->phps= mem->handlers->calloc(mem, hphp->size, sizeof(xc_entry_data_php_t*)), "phps OOM");
     1471        }
    13081472        CHECK(cache->lck     = xc_lock_init(NULL), "can't create lock");
    13091473
    13101474        cache->hcache  = hcache;
    13111475        cache->hentry  = hentry;
     1476        cache->hphp    = hphp;
    13121477        cache->shm     = shm;
    13131478        cache->mem     = mem;
     
    13641529            zend_compile_file = xc_compile_file;
    13651530
    1366             CHECK(xc_php_caches = xc_cache_init(shm, &xc_php_hcache, &xc_php_hentry, xc_php_size), "failed init opcode cache");
     1531            CHECK(xc_php_caches = xc_cache_init(shm, &xc_php_hcache, &xc_php_hentry, &xc_php_hentry, xc_php_size), "failed init opcode cache");
    13671532        }
    13681533
    13691534        if (xc_var_size) {
    1370             CHECK(xc_var_caches = xc_cache_init(shm, &xc_var_hcache, &xc_var_hentry, xc_var_size), "failed init variable cache");
     1535            CHECK(xc_var_caches = xc_cache_init(shm, &xc_var_hcache, &xc_var_hentry, NULL, xc_var_size), "failed init variable cache");
    13711536        }
    13721537    }
     
    17151880        if (stored_xce) {
    17161881            if (!VAR_ENTRY_EXPIRED(stored_xce)) {
    1717                 xc_processor_restore_zval(return_value, stored_xce->data.var->value, stored_xce->have_references TSRMLS_CC);
     1882                xc_processor_restore_zval(return_value, stored_xce->data.var->value, stored_xce->data.var->have_references TSRMLS_CC);
    17181883                /* return */
    17191884                break;
     
    18642029                else {
    18652030                    TRACE("%s", "incdec: notlong");
    1866                     xc_processor_restore_zval(&oldzval, stored_xce->data.var->value, stored_xce->have_references TSRMLS_CC);
     2031                    xc_processor_restore_zval(&oldzval, stored_xce->data.var->value, stored_xce->data.var->have_references TSRMLS_CC);
    18672032                    convert_to_long(&oldzval);
    18682033                    value = Z_LVAL(oldzval);
Note: See TracChangeset for help on using the changeset viewer.