mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Implemented registry cache that prevent registry lookup on each request. In case of modification of corresponding registry-tree PHP will reload it automatic.
This commit is contained in:
3
NEWS
3
NEWS
@@ -5,6 +5,9 @@ PHP NEWS
|
||||
. removed unnecessary checks for ISREG file and corresponding stat() calls
|
||||
. opendir() is reimplemented using GetFistFile/GetNextFile those are faster
|
||||
then _findfirst/_findnext
|
||||
. implemented registry cache that prevent registry lookup on each request.
|
||||
In case of modification of corresponding registry-tree PHP will reload
|
||||
it automatic
|
||||
- Zend Memory Manager Improvements (Dmitry)
|
||||
. use HeapAlloc() instead of VirtualAlloc()
|
||||
. use "win32" storage manager (instead of "malloc") on Windows by default
|
||||
|
||||
@@ -3940,7 +3940,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);
|
||||
@@ -4065,6 +4065,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);
|
||||
|
||||
@@ -1458,7 +1458,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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
190
win32/registry.c
190
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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user