From 768185e58f08295ef52b550ce9cbb41768d0fdb3 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 10 Nov 2006 11:42:40 +0000 Subject: [PATCH] Implemented registry cache that prevent registry lookup on each request. In case of modification of corresponding registry-tree PHP will reload it automatic. --- ext/standard/basic_functions.c | 5 +- main/main.c | 2 +- win32/globals.c | 26 ++++- win32/php_win32_globals.h | 5 + win32/registry.c | 190 ++++++++++++++++++++++++++------- 5 files changed, 187 insertions(+), 41 deletions(-) diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 3d62891751..1194ec7d2a 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -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); diff --git a/main/main.c b/main/main.c index e26a740aa8..34461c56d5 100644 --- a/main/main.c +++ b/main/main.c @@ -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; diff --git a/win32/globals.c b/win32/globals.c index ae9120095c..a8bf3238c0 100755 --- a/win32/globals.c +++ b/win32/globals.c @@ -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; } diff --git a/win32/php_win32_globals.h b/win32/php_win32_globals.h index c130d5bc50..36d28e2beb 100755 --- a/win32/php_win32_globals.h +++ b/win32/php_win32_globals.h @@ -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 diff --git a/win32/registry.c b/win32/registry.c index 2e7a074091..e96bf91871 100644 --- a/win32/registry.c +++ b/win32/registry.c @@ -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); } -- 2.40.0