]> granicus.if.org Git - php/commitdiff
Implemented registry cache that prevent registry lookup on each request. In case...
authorDmitry Stogov <dmitry@php.net>
Fri, 10 Nov 2006 11:42:40 +0000 (11:42 +0000)
committerDmitry Stogov <dmitry@php.net>
Fri, 10 Nov 2006 11:42:40 +0000 (11:42 +0000)
ext/standard/basic_functions.c
main/main.c
win32/globals.c
win32/php_win32_globals.h
win32/registry.c

index 3d628917510f145acc0be4737af8fc924b60fa84..1194ec7d2ab9f505a599abcebb19af8bf94d94b3 100644 (file)
@@ -3950,7 +3950,7 @@ PHP_MINIT_FUNCTION(basic)
 #ifdef ZTS
        ts_allocate_id(&basic_globals_id, sizeof(php_basic_globals), (ts_allocate_ctor) basic_globals_ctor, (ts_allocate_dtor) basic_globals_dtor);
 #ifdef PHP_WIN32
-       ts_allocate_id(&php_win32_core_globals_id, sizeof(php_win32_core_globals), (ts_allocate_ctor)php_win32_core_globals_ctor, NULL);
+       ts_allocate_id(&php_win32_core_globals_id, sizeof(php_win32_core_globals), (ts_allocate_ctor)php_win32_core_globals_ctor, (ts_allocate_dtor)php_win32_core_globals_dtor );
 #endif
 #else
        basic_globals_ctor(&basic_globals TSRMLS_CC);
@@ -4073,6 +4073,9 @@ PHP_MSHUTDOWN_FUNCTION(basic)
 #endif
 #else
        basic_globals_dtor(&basic_globals TSRMLS_CC);
+#ifdef PHP_WIN32
+       php_win32_core_globals_dtor(&the_php_win32_core_globals TSRMLS_CC);
+#endif
 #endif
 
        php_unregister_url_stream_wrapper("php" TSRMLS_CC);
index e26a740aa85df095588fcde592da88836bb19a7c..34461c56d53a2284ea6693cfa4251b89a13a293a 100644 (file)
@@ -1577,7 +1577,7 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
        ts_allocate_id(&core_globals_id, sizeof(php_core_globals), (ts_allocate_ctor) core_globals_ctor, (ts_allocate_dtor) core_globals_dtor);
        core_globals = ts_resource(core_globals_id);
 #ifdef PHP_WIN32
-       ts_allocate_id(&php_win32_core_globals_id, sizeof(php_win32_core_globals), (ts_allocate_ctor) php_win32_core_globals_ctor, NULL);
+       ts_allocate_id(&php_win32_core_globals_id, sizeof(php_win32_core_globals), (ts_allocate_ctor) php_win32_core_globals_ctor, (ts_allocate_dtor) php_win32_core_globals_dtor);
 #endif
 #endif
        EG(bailout) = NULL;
index ae9120095c8f5e3774ed007565a22098fb45a1e1..a8bf3238c00f7396329f6d9b273ca237996bf49f 100755 (executable)
@@ -20,6 +20,7 @@
 
 #include "php.h"
 #include "php_win32_globals.h"
+#include "syslog.h"
 
 #ifdef ZTS
 PHPAPI int php_win32_core_globals_id;
@@ -33,6 +34,26 @@ void php_win32_core_globals_ctor(void *vg TSRMLS_DC)
        memset(wg, 0, sizeof(*wg));
 }
 
+void php_win32_core_globals_dtor(void *vg TSRMLS_DC)
+{
+       php_win32_core_globals *wg = (php_win32_core_globals*)vg;
+
+       if (wg->registry_key) {
+               RegCloseKey(wg->registry_key);
+               wg->registry_key = NULL;
+       }
+       if (wg->registry_event) {
+               CloseHandle(wg->registry_event);
+               wg->registry_event = NULL;
+       }
+       if (wg->registry_directories) {
+               zend_hash_destroy(wg->registry_directories);
+               free(wg->registry_directories);
+               wg->registry_directories = NULL;
+       }
+}
+
+
 PHP_RSHUTDOWN_FUNCTION(win32_core_globals)
 {
        php_win32_core_globals *wg =
@@ -43,7 +64,10 @@ PHP_RSHUTDOWN_FUNCTION(win32_core_globals)
 #endif
                ;
 
-       memset(wg, 0, sizeof(*wg));
+       closelog();
+       wg->starttime.tv_sec = 0;
+       wg->lasttime = 0;
+
        return SUCCESS;
 }
 
index c130d5bc507b523ec1993196ec3f675cf2e97300..36d28e2beb446c325e0f18c76de01cc5477febaf 100755 (executable)
@@ -41,9 +41,14 @@ struct _php_win32_core_globals {
        /* time */
        struct timeval starttime;
        __int64                 lasttime, freq;
+
+       HKEY       registry_key;
+       HANDLE     registry_event;
+       HashTable *registry_directories;
 };
 
 void php_win32_core_globals_ctor(void *vg TSRMLS_DC);
+void php_win32_core_globals_dtor(void *vg TSRMLS_DC);
 PHP_RSHUTDOWN_FUNCTION(win32_core_globals);
 
 #endif
index 2e7a074091b8a02e0eea7700e027888d16af1448..e96bf918718e76144dd0e3350e2437c14b718662 100644 (file)
@@ -1,5 +1,6 @@
 #include "php.h"
 #include "php_ini.h"
+#include "php_win32_globals.h"
 
 #define PHP_REGISTRY_KEY              "SOFTWARE\\PHP"
 
@@ -56,13 +57,135 @@ static int OpenPhpRegistryKey(char* sub_key, HKEY *hKey)
        return 0;
 }
 
+static int LoadDirectory(HashTable *directories, HKEY key, char *path, int path_len, HashTable *parent_ht)
+{
+       DWORD keys, values, max_key, max_name, max_value;
+       int ret = 0;
+       HashTable *ht = NULL;
+
+       if (RegQueryInfoKey(key, NULL, NULL, NULL, &keys, &max_key, NULL, &values, &max_name, &max_value, NULL, NULL) == ERROR_SUCCESS) {
+               
+               if (values) {
+                       DWORD i;
+                       char *name = (char*)emalloc(max_name+1);
+                       char *value = (char*)emalloc(max_value+1);
+                       DWORD name_len, type, value_len;
+                       zval *data;
+
+                       for (i = 0; i < values; i++) {
+                               name_len = max_name+1;
+                               value_len = max_value+1;
+                               if (RegEnumValue(key, i, name, &name_len, NULL, &type, value, &value_len) == ERROR_SUCCESS) {
+                                       if ((type == REG_SZ) || (type == REG_EXPAND_SZ)) {
+                                               if (!ht) {
+                                                       ht = (HashTable*)malloc(sizeof(HashTable));
+                                                       zend_hash_init(ht, 0, NULL, ZVAL_INTERNAL_PTR_DTOR, 1);
+                                               }
+                                               data = (zval*)malloc(sizeof(zval));
+                                               INIT_PZVAL(data);
+                                               Z_STRVAL_P(data) = zend_strndup(value, value_len-1);
+                                               Z_STRLEN_P(data) = value_len-1;
+                                               zend_hash_update(ht, name, name_len+1, &data, sizeof(zval*), NULL);
+                                       }
+                               }
+                       }
+                       if (ht) {
+                               if (parent_ht) {
+                                       HashPosition pos;
+                                       char *index;
+                                       uint index_len;
+                                       ulong num;
+                                       zval **data;
+
+                                       for (zend_hash_internal_pointer_reset_ex(parent_ht, &pos);
+                                            zend_hash_get_current_data_ex(parent_ht, (void**)&data, &pos) == SUCCESS &&
+                                            zend_hash_get_current_key_ex(parent_ht, &index, &index_len, &num, 0, &pos) == HASH_KEY_IS_STRING;
+                                            zend_hash_move_forward_ex(parent_ht, &pos)) {
+                                               if (zend_hash_add(ht, index, index_len, data, sizeof(zval*), NULL) == SUCCESS) {
+                                                   (*data)->refcount++;
+                                               }
+                                       }
+                               }
+                               zend_hash_update(directories, path, path_len+1, &ht, sizeof(HashTable*), NULL);
+                               ret = 1;
+                       }
+
+                       efree(name);
+                       efree(value);
+               }
+
+               if (ht == NULL) {
+                       ht = parent_ht;
+               }
+
+               if (keys) {
+                       DWORD i;
+                       char *name = (char*)emalloc(max_key+1);
+                       char *new_path = (char*)emalloc(path_len+max_key+2);
+                       DWORD name_len;
+                       FILETIME t;
+                       HKEY subkey;
+
+                       for (i = 0; i < keys; i++) {
+                               name_len = max_key+1;
+                               if (RegEnumKeyEx(key, i, name, &name_len, NULL, NULL, NULL, &t) == ERROR_SUCCESS) {
+                                       if (RegOpenKeyEx(key, name, 0, KEY_READ, &subkey) == ERROR_SUCCESS) {
+                                               if (path_len) {
+                                                       memcpy(new_path, path, path_len);
+                                                       new_path[path_len] = '/';
+                                                       path_len++;
+                                               }
+                                               memcpy(new_path+path_len, name, name_len+1);
+                                               zend_str_tolower(new_path, path_len+name_len);
+                                               if (LoadDirectory(directories, subkey, new_path, path_len+name_len, ht)) {
+                                                       ret = 1;
+                                               }
+                                               RegCloseKey(subkey);
+                                       }
+                               }
+                       }
+                       efree(new_path);
+                       efree(name);
+               }
+       }
+       return ret;
+}
+
+static void delete_internal_hashtable(void *data)
+{
+       zend_hash_destroy(*(HashTable**)data);
+       free(*(HashTable**)data);
+}
+
+#define RegNotifyFlags (REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_ATTRIBUTES | REG_NOTIFY_CHANGE_LAST_SET)
+
 void UpdateIniFromRegistry(char *path TSRMLS_DC)
 {
        char *p, *orig_path;
-       HKEY MainKey;
-       char *strtok_buf = NULL;
+       int path_len;
+       HashTable **pht;
 
-       if (!OpenPhpRegistryKey("\\Per Directory Values", &MainKey)) {
+       if (!PW32G(registry_directories)) {
+               PW32G(registry_directories) = (HashTable*)malloc(sizeof(HashTable));
+               zend_hash_init(PW32G(registry_directories), 0, NULL, delete_internal_hashtable, 1);
+               if (!OpenPhpRegistryKey("\\Per Directory Values", &PW32G(registry_key))) {
+                       PW32G(registry_key) = NULL;
+                       return;
+               }
+               PW32G(registry_event) = CreateEvent(NULL, TRUE, FALSE, NULL);
+               if (PW32G(registry_event)) {
+                       RegNotifyChangeKeyValue(PW32G(registry_key), TRUE, RegNotifyFlags, PW32G(registry_event), TRUE);
+               }
+               if (!LoadDirectory(PW32G(registry_directories), PW32G(registry_key), "", 0, NULL)) {
+                       return;
+               }
+       } else if (PW32G(registry_event) && WaitForSingleObject(PW32G(registry_event), 0) == WAIT_OBJECT_0) {
+               RegNotifyChangeKeyValue(PW32G(registry_key), TRUE, RegNotifyFlags, PW32G(registry_event), TRUE);
+               zend_hash_clean(PW32G(registry_directories));
+               if (!LoadDirectory(PW32G(registry_directories), PW32G(registry_key), "", 0, NULL)) {
+                       return;
+               }
+       } else if (zend_hash_num_elements(PW32G(registry_directories)) == 0) {
                return;
        }
 
@@ -101,48 +224,39 @@ void UpdateIniFromRegistry(char *path TSRMLS_DC)
                }
        }
 
-
-       path = p = php_strtok_r(path, "\\/", &strtok_buf);
-
-       while (p) {
-               HKEY hKey;
-               DWORD lType;
-               DWORD values = 0, max_name = 0, max_value = 0, i = 0;
-               
-               if (p>path) {
-                       *(p-1) = '\\'; /* restore the slash */
+       path_len = 0;
+       while (path[path_len] != 0) {
+               if (path[path_len] == '\\') {
+                       path[path_len] = '/';
                }
+               path_len++;
+       }
+       zend_str_tolower(path, path_len);
+       while (path_len >= 0) {
+               if (zend_hash_find(PW32G(registry_directories), path, path_len+1, (void**)&pht) == SUCCESS) {
+                       HashTable *ht = *pht;
+                       HashPosition pos;
+                       char *index;
+                       uint index_len;
+                       ulong num;
+                       zval **data;
 
-               if (RegOpenKeyEx(MainKey, path, 0, KEY_READ, &hKey)!=ERROR_SUCCESS) {
+                       for (zend_hash_internal_pointer_reset_ex(ht, &pos);
+                            zend_hash_get_current_data_ex(ht, (void**)&data, &pos) == SUCCESS &&
+                            zend_hash_get_current_key_ex(ht, &index, &index_len, &num, 0, &pos) == HASH_KEY_IS_STRING;
+                            zend_hash_move_forward_ex(ht, &pos)) {
+                               zend_alter_ini_entry(index, index_len, Z_STRVAL_PP(data), Z_STRLEN_PP(data), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
+                       }
                        break;
                }
-
-               if(RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &values, &max_name, &max_value, NULL, NULL) == ERROR_SUCCESS) {
-                       LPTSTR namebuf = (LPTSTR)emalloc(max_name + 1);
-                       PBYTE valuebuf = (PBYTE)emalloc(max_value);
-
-                       while (i < values) {
-                               DWORD namebuf_len  = max_name + 1;
-                               DWORD valuebuf_len = max_value;
-
-                               RegEnumValue(hKey, i, namebuf, &namebuf_len, NULL, &lType, valuebuf, &valuebuf_len);
-
-                               if ((lType == REG_SZ) || (lType == REG_EXPAND_SZ)) {
-                                       /* valuebuf_len includes trailing 0 */
-                                       zend_alter_ini_entry(namebuf, namebuf_len + 1, valuebuf, valuebuf_len?valuebuf_len-1:0, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
-                               }
-
-                               i++;
+               if (--path_len > 0) {
+                       while (path_len > 0 && path[path_len] != '/') {
+                               path_len--;
                        }
-
-                       efree(namebuf);
-                       efree(valuebuf);
                }
-
-               RegCloseKey(hKey);
-               p = php_strtok_r(NULL, "\\/", &strtok_buf);
+               path[path_len] = 0;
        }
-       RegCloseKey(MainKey);
+
        efree(orig_path);
 }