Skip to content

Commit 532b02c

Browse files
committedNov 10, 2006
Implemented registry cache that prevent registry lookup on each request. In case of modification of corresponding registry-tree PHP will reload it automatic.
1 parent 41c81f2 commit 532b02c

File tree

6 files changed

+190
-41
lines changed

6 files changed

+190
-41
lines changed
 

‎NEWS

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ PHP NEWS
55
. removed unnecessary checks for ISREG file and corresponding stat() calls
66
. opendir() is reimplemented using GetFistFile/GetNextFile those are faster
77
then _findfirst/_findnext
8+
. implemented registry cache that prevent registry lookup on each request.
9+
In case of modification of corresponding registry-tree PHP will reload
10+
it automatic
811
- Zend Memory Manager Improvements (Dmitry)
912
. use HeapAlloc() instead of VirtualAlloc()
1013
. use "win32" storage manager (instead of "malloc") on Windows by default

‎ext/standard/basic_functions.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -3940,7 +3940,7 @@ PHP_MINIT_FUNCTION(basic)
39403940
#ifdef ZTS
39413941
ts_allocate_id(&basic_globals_id, sizeof(php_basic_globals), (ts_allocate_ctor) basic_globals_ctor, (ts_allocate_dtor) basic_globals_dtor);
39423942
#ifdef PHP_WIN32
3943-
ts_allocate_id(&php_win32_core_globals_id, sizeof(php_win32_core_globals), (ts_allocate_ctor)php_win32_core_globals_ctor, NULL);
3943+
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 );
39443944
#endif
39453945
#else
39463946
basic_globals_ctor(&basic_globals TSRMLS_CC);
@@ -4065,6 +4065,9 @@ PHP_MSHUTDOWN_FUNCTION(basic)
40654065
#endif
40664066
#else
40674067
basic_globals_dtor(&basic_globals TSRMLS_CC);
4068+
#ifdef PHP_WIN32
4069+
php_win32_core_globals_dtor(&the_php_win32_core_globals TSRMLS_CC);
4070+
#endif
40684071
#endif
40694072

40704073
php_unregister_url_stream_wrapper("php" TSRMLS_CC);

‎main/main.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1458,7 +1458,7 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
14581458
ts_allocate_id(&core_globals_id, sizeof(php_core_globals), (ts_allocate_ctor) core_globals_ctor, (ts_allocate_dtor) core_globals_dtor);
14591459
core_globals = ts_resource(core_globals_id);
14601460
#ifdef PHP_WIN32
1461-
ts_allocate_id(&php_win32_core_globals_id, sizeof(php_win32_core_globals), (ts_allocate_ctor) php_win32_core_globals_ctor, NULL);
1461+
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);
14621462
#endif
14631463
#endif
14641464
EG(bailout) = NULL;

‎win32/globals.c

+25-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include "php.h"
2222
#include "php_win32_globals.h"
23+
#include "syslog.h"
2324

2425
#ifdef ZTS
2526
PHPAPI int php_win32_core_globals_id;
@@ -33,6 +34,26 @@ void php_win32_core_globals_ctor(void *vg TSRMLS_DC)
3334
memset(wg, 0, sizeof(*wg));
3435
}
3536

37+
void php_win32_core_globals_dtor(void *vg TSRMLS_DC)
38+
{
39+
php_win32_core_globals *wg = (php_win32_core_globals*)vg;
40+
41+
if (wg->registry_key) {
42+
RegCloseKey(wg->registry_key);
43+
wg->registry_key = NULL;
44+
}
45+
if (wg->registry_event) {
46+
CloseHandle(wg->registry_event);
47+
wg->registry_event = NULL;
48+
}
49+
if (wg->registry_directories) {
50+
zend_hash_destroy(wg->registry_directories);
51+
free(wg->registry_directories);
52+
wg->registry_directories = NULL;
53+
}
54+
}
55+
56+
3657
PHP_RSHUTDOWN_FUNCTION(win32_core_globals)
3758
{
3859
php_win32_core_globals *wg =
@@ -43,7 +64,10 @@ PHP_RSHUTDOWN_FUNCTION(win32_core_globals)
4364
#endif
4465
;
4566

46-
memset(wg, 0, sizeof(*wg));
67+
closelog();
68+
wg->starttime.tv_sec = 0;
69+
wg->lasttime = 0;
70+
4771
return SUCCESS;
4872
}
4973

‎win32/php_win32_globals.h

+5
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,14 @@ struct _php_win32_core_globals {
4141
/* time */
4242
struct timeval starttime;
4343
__int64 lasttime, freq;
44+
45+
HKEY registry_key;
46+
HANDLE registry_event;
47+
HashTable *registry_directories;
4448
};
4549

4650
void php_win32_core_globals_ctor(void *vg TSRMLS_DC);
51+
void php_win32_core_globals_dtor(void *vg TSRMLS_DC);
4752
PHP_RSHUTDOWN_FUNCTION(win32_core_globals);
4853

4954
#endif

‎win32/registry.c

+152-38
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "php.h"
22
#include "php_ini.h"
3+
#include "php_win32_globals.h"
34

45
#define PHP_REGISTRY_KEY "SOFTWARE\\PHP"
56

@@ -56,13 +57,135 @@ static int OpenPhpRegistryKey(char* sub_key, HKEY *hKey)
5657
return 0;
5758
}
5859

60+
static int LoadDirectory(HashTable *directories, HKEY key, char *path, int path_len, HashTable *parent_ht)
61+
{
62+
DWORD keys, values, max_key, max_name, max_value;
63+
int ret = 0;
64+
HashTable *ht = NULL;
65+
66+
if (RegQueryInfoKey(key, NULL, NULL, NULL, &keys, &max_key, NULL, &values, &max_name, &max_value, NULL, NULL) == ERROR_SUCCESS) {
67+
68+
if (values) {
69+
DWORD i;
70+
char *name = (char*)emalloc(max_name+1);
71+
char *value = (char*)emalloc(max_value+1);
72+
DWORD name_len, type, value_len;
73+
zval *data;
74+
75+
for (i = 0; i < values; i++) {
76+
name_len = max_name+1;
77+
value_len = max_value+1;
78+
if (RegEnumValue(key, i, name, &name_len, NULL, &type, value, &value_len) == ERROR_SUCCESS) {
79+
if ((type == REG_SZ) || (type == REG_EXPAND_SZ)) {
80+
if (!ht) {
81+
ht = (HashTable*)malloc(sizeof(HashTable));
82+
zend_hash_init(ht, 0, NULL, ZVAL_INTERNAL_PTR_DTOR, 1);
83+
}
84+
data = (zval*)malloc(sizeof(zval));
85+
INIT_PZVAL(data);
86+
Z_STRVAL_P(data) = zend_strndup(value, value_len-1);
87+
Z_STRLEN_P(data) = value_len-1;
88+
zend_hash_update(ht, name, name_len+1, &data, sizeof(zval*), NULL);
89+
}
90+
}
91+
}
92+
if (ht) {
93+
if (parent_ht) {
94+
HashPosition pos;
95+
char *index;
96+
uint index_len;
97+
ulong num;
98+
zval **data;
99+
100+
for (zend_hash_internal_pointer_reset_ex(parent_ht, &pos);
101+
zend_hash_get_current_data_ex(parent_ht, (void**)&data, &pos) == SUCCESS &&
102+
zend_hash_get_current_key_ex(parent_ht, &index, &index_len, &num, 0, &pos) == HASH_KEY_IS_STRING;
103+
zend_hash_move_forward_ex(parent_ht, &pos)) {
104+
if (zend_hash_add(ht, index, index_len, data, sizeof(zval*), NULL) == SUCCESS) {
105+
(*data)->refcount++;
106+
}
107+
}
108+
}
109+
zend_hash_update(directories, path, path_len+1, &ht, sizeof(HashTable*), NULL);
110+
ret = 1;
111+
}
112+
113+
efree(name);
114+
efree(value);
115+
}
116+
117+
if (ht == NULL) {
118+
ht = parent_ht;
119+
}
120+
121+
if (keys) {
122+
DWORD i;
123+
char *name = (char*)emalloc(max_key+1);
124+
char *new_path = (char*)emalloc(path_len+max_key+2);
125+
DWORD name_len;
126+
FILETIME t;
127+
HKEY subkey;
128+
129+
for (i = 0; i < keys; i++) {
130+
name_len = max_key+1;
131+
if (RegEnumKeyEx(key, i, name, &name_len, NULL, NULL, NULL, &t) == ERROR_SUCCESS) {
132+
if (RegOpenKeyEx(key, name, 0, KEY_READ, &subkey) == ERROR_SUCCESS) {
133+
if (path_len) {
134+
memcpy(new_path, path, path_len);
135+
new_path[path_len] = '/';
136+
path_len++;
137+
}
138+
memcpy(new_path+path_len, name, name_len+1);
139+
zend_str_tolower(new_path, path_len+name_len);
140+
if (LoadDirectory(directories, subkey, new_path, path_len+name_len, ht)) {
141+
ret = 1;
142+
}
143+
RegCloseKey(subkey);
144+
}
145+
}
146+
}
147+
efree(new_path);
148+
efree(name);
149+
}
150+
}
151+
return ret;
152+
}
153+
154+
static void delete_internal_hashtable(void *data)
155+
{
156+
zend_hash_destroy(*(HashTable**)data);
157+
free(*(HashTable**)data);
158+
}
159+
160+
#define RegNotifyFlags (REG_NOTIFY_CHANGE_NAME | REG_NOTIFY_CHANGE_ATTRIBUTES | REG_NOTIFY_CHANGE_LAST_SET)
161+
59162
void UpdateIniFromRegistry(char *path TSRMLS_DC)
60163
{
61164
char *p, *orig_path;
62-
HKEY MainKey;
63-
char *strtok_buf = NULL;
165+
int path_len;
166+
HashTable **pht;
64167

65-
if (!OpenPhpRegistryKey("\\Per Directory Values", &MainKey)) {
168+
if (!PW32G(registry_directories)) {
169+
PW32G(registry_directories) = (HashTable*)malloc(sizeof(HashTable));
170+
zend_hash_init(PW32G(registry_directories), 0, NULL, delete_internal_hashtable, 1);
171+
if (!OpenPhpRegistryKey("\\Per Directory Values", &PW32G(registry_key))) {
172+
PW32G(registry_key) = NULL;
173+
return;
174+
}
175+
PW32G(registry_event) = CreateEvent(NULL, TRUE, FALSE, NULL);
176+
if (PW32G(registry_event)) {
177+
RegNotifyChangeKeyValue(PW32G(registry_key), TRUE, RegNotifyFlags, PW32G(registry_event), TRUE);
178+
}
179+
if (!LoadDirectory(PW32G(registry_directories), PW32G(registry_key), "", 0, NULL)) {
180+
return;
181+
}
182+
} else if (PW32G(registry_event) && WaitForSingleObject(PW32G(registry_event), 0) == WAIT_OBJECT_0) {
183+
RegNotifyChangeKeyValue(PW32G(registry_key), TRUE, RegNotifyFlags, PW32G(registry_event), TRUE);
184+
zend_hash_clean(PW32G(registry_directories));
185+
if (!LoadDirectory(PW32G(registry_directories), PW32G(registry_key), "", 0, NULL)) {
186+
return;
187+
}
188+
} else if (zend_hash_num_elements(PW32G(registry_directories)) == 0) {
66189
return;
67190
}
68191

@@ -101,48 +224,39 @@ void UpdateIniFromRegistry(char *path TSRMLS_DC)
101224
}
102225
}
103226

104-
105-
path = p = php_strtok_r(path, "\\/", &strtok_buf);
106-
107-
while (p) {
108-
HKEY hKey;
109-
DWORD lType;
110-
DWORD values = 0, max_name = 0, max_value = 0, i = 0;
111-
112-
if (p>path) {
113-
*(p-1) = '\\'; /* restore the slash */
227+
path_len = 0;
228+
while (path[path_len] != 0) {
229+
if (path[path_len] == '\\') {
230+
path[path_len] = '/';
114231
}
232+
path_len++;
233+
}
234+
zend_str_tolower(path, path_len);
235+
while (path_len >= 0) {
236+
if (zend_hash_find(PW32G(registry_directories), path, path_len+1, (void**)&pht) == SUCCESS) {
237+
HashTable *ht = *pht;
238+
HashPosition pos;
239+
char *index;
240+
uint index_len;
241+
ulong num;
242+
zval **data;
115243

116-
if (RegOpenKeyEx(MainKey, path, 0, KEY_READ, &hKey)!=ERROR_SUCCESS) {
244+
for (zend_hash_internal_pointer_reset_ex(ht, &pos);
245+
zend_hash_get_current_data_ex(ht, (void**)&data, &pos) == SUCCESS &&
246+
zend_hash_get_current_key_ex(ht, &index, &index_len, &num, 0, &pos) == HASH_KEY_IS_STRING;
247+
zend_hash_move_forward_ex(ht, &pos)) {
248+
zend_alter_ini_entry(index, index_len, Z_STRVAL_PP(data), Z_STRLEN_PP(data), PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
249+
}
117250
break;
118251
}
119-
120-
if(RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &values, &max_name, &max_value, NULL, NULL) == ERROR_SUCCESS) {
121-
LPTSTR namebuf = (LPTSTR)emalloc(max_name + 1);
122-
PBYTE valuebuf = (PBYTE)emalloc(max_value);
123-
124-
while (i < values) {
125-
DWORD namebuf_len = max_name + 1;
126-
DWORD valuebuf_len = max_value;
127-
128-
RegEnumValue(hKey, i, namebuf, &namebuf_len, NULL, &lType, valuebuf, &valuebuf_len);
129-
130-
if ((lType == REG_SZ) || (lType == REG_EXPAND_SZ)) {
131-
/* valuebuf_len includes trailing 0 */
132-
zend_alter_ini_entry(namebuf, namebuf_len + 1, valuebuf, valuebuf_len?valuebuf_len-1:0, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);
133-
}
134-
135-
i++;
252+
if (--path_len > 0) {
253+
while (path_len > 0 && path[path_len] != '/') {
254+
path_len--;
136255
}
137-
138-
efree(namebuf);
139-
efree(valuebuf);
140256
}
141-
142-
RegCloseKey(hKey);
143-
p = php_strtok_r(NULL, "\\/", &strtok_buf);
257+
path[path_len] = 0;
144258
}
145-
RegCloseKey(MainKey);
259+
146260
efree(orig_path);
147261
}
148262

0 commit comments

Comments
 (0)
Failed to load comments.