34# error mm is not thread-safe
37#define PS_MM_FILE "session_mm_"
59static ps_mm *ps_mm_instance =
NULL;
62# define ps_mm_debug(a) printf a
64# define ps_mm_debug(a)
73 for (h = 2166136261U; data_char < e; ) {
81static void hash_split(ps_mm *
data)
85 ps_sd **ohash, **ehash;
88 nmax = ((
data->hash_max + 1) << 1) - 1;
89 nhash = mm_calloc(
data->mm, nmax + 1,
sizeof(*
data->hash));
96 ehash =
data->hash +
data->hash_max + 1;
97 for (ohash =
data->hash; ohash < ehash; ohash++) {
98 for (ps = *ohash; ps; ps =
next) {
100 ps->next = nhash[ps->hv & nmax];
101 nhash[ps->hv & nmax] = ps;
107 data->hash_max = nmax;
122 hv = ps_sd_hash(
key);
123 slot = hv &
data->hash_max;
128 sd->alloclen = sd->datalen = 0;
130 sd->key = zend_string_copy(
key);
132 sd->next =
data->hash[slot];
133 data->hash[slot] = sd;
138 if (
data->hash_cnt >=
data->hash_max) {
143 ps_mm_debug((
"inserting %s(%p) into slot %d\n",
ZSTR_VAL(
key), sd, slot));
148static void ps_sd_destroy(ps_mm *
data, ps_sd *sd)
152 slot = ps_sd_hash(sd->key) &
data->hash_max;
154 if (
data->hash[slot] == sd) {
155 data->hash[slot] = sd->next;
161 prev->next = sd->next;
167 mm_free(
data->mm, sd->data);
169 zend_string_release(sd->key);
171 mm_free(
data->mm, sd);
179 hv = ps_sd_hash(
key);
180 slot = hv &
data->hash_max;
183 if (
ret->hv == hv && zend_string_equals(
ret->key,
key)) {
198 ps_mm_debug((
"lookup(%s): ret=%p,hv=%u,slot=%d\n",
ZSTR_VAL(
key),
ret, hv, slot));
210 sd = ps_sd_lookup(
data,
key, 0);
221#define PS_MM_DATA ps_mm *data = PS_GET_MOD_DATA()
225 data->owner = getpid();
226 data->mm = mm_create(0, path);
232 data->hash_max = 511;
233 data->hash = mm_calloc(
data->mm,
data->hash_max + 1,
sizeof(ps_sd *));
235 mm_destroy(
data->mm);
242static void ps_mm_destroy(ps_mm *
data)
249 if (
data->owner != getpid()) {
253 for (
int h = 0; h <
data->hash_max + 1; h++) {
254 for (sd =
data->hash[h]; sd; sd =
next) {
256 ps_sd_destroy(
data, sd);
261 mm_destroy(
data->mm);
267 size_t save_path_len =
strlen(
PS(save_path));
270 char *ps_mm_path, euid[30];
273 ps_mm_instance = calloc(
sizeof(*ps_mm_instance), 1);
274 if (!ps_mm_instance) {
278 if (!(euid_len =
slprintf(euid,
sizeof(euid),
"%d", geteuid()))) {
279 free(ps_mm_instance);
280 ps_mm_instance =
NULL;
285 ps_mm_path =
emalloc(save_path_len + 1 + (
sizeof(PS_MM_FILE) - 1) + mod_name_len + euid_len + 1);
287 memcpy(ps_mm_path,
PS(save_path), save_path_len);
288 if (save_path_len &&
PS(save_path)[save_path_len - 1] !=
DEFAULT_SLASH) {
292 memcpy(ps_mm_path + save_path_len, PS_MM_FILE,
sizeof(PS_MM_FILE) - 1);
293 save_path_len +=
sizeof(PS_MM_FILE) - 1;
295 save_path_len += mod_name_len;
296 memcpy(ps_mm_path + save_path_len, euid, euid_len);
297 ps_mm_path[save_path_len + euid_len] =
'\0';
299 ret = ps_mm_initialize(ps_mm_instance, ps_mm_path);
304 free(ps_mm_instance);
305 ps_mm_instance =
NULL;
315 if (ps_mm_instance) {
316 ps_mm_destroy(ps_mm_instance);
324 ps_mm_debug((
"open: ps_mm_instance=%p\n", ps_mm_instance));
326 if (!ps_mm_instance) {
347 mm_lock(
data->mm, MM_LOCK_RD);
350 if (
PS(use_strict_mode)
357 PS(
id) =
PS(mod)->s_create_sid((
void **)&
data);
361 if (
PS(use_cookies)) {
368 sd = ps_sd_lookup(
data,
PS(
id), 0);
370 *
val = zend_string_init(sd->data, sd->datalen, 0);
384 mm_lock(
data->mm, MM_LOCK_RW);
386 sd = ps_sd_lookup(
data,
key, 1);
389 ps_mm_debug((
"new entry for %s\n",
ZSTR_VAL(
key)));
393 if (
val->len >= sd->alloclen) {
395 mm_free(
data->mm, sd->data);
397 sd->alloclen =
val->len + 1;
398 sd->data = mm_malloc(
data->mm, sd->alloclen);
401 ps_sd_destroy(
data, sd);
407 sd->datalen =
val->len;
423 mm_lock(
data->mm, MM_LOCK_RW);
425 sd = ps_sd_lookup(
data,
key, 0);
427 ps_sd_destroy(
data, sd);
439 ps_sd **ohash, **ehash;
443 ps_mm_debug((
"gc\n"));
447 limit -= maxlifetime;
449 mm_lock(
data->mm, MM_LOCK_RW);
451 ehash =
data->hash +
data->hash_max + 1;
452 for (ohash =
data->hash; ohash < ehash; ohash++) {
453 for (sd = *ohash; sd; sd =
next) {
455 if (sd->ctime < limit) {
456 ps_mm_debug((
"purging %s\n",
ZSTR_VAL(sd->key)));
457 ps_sd_destroy(
data, sd);
SAPI_API sapi_module_struct sapi_module
prev(array|object &$array)
hash(string $algo, string $data, bool $binary=false, array $options=[])
PHPAPI ZEND_COLD void php_error_docref(const char *docref, int type, const char *format,...)
#define PHP_MSHUTDOWN_FUNCTION
#define PHP_MINIT_FUNCTION
unsigned char key[REFLECTION_KEY_LEN]
PHPAPI zend_result php_session_register_module(const ps_module *)
struct ps_module_struct ps_module
PHPAPI zend_result php_session_reset_id(void)
#define PS_SET_MOD_DATA(a)
#define PS_DESTROY_FUNC(x)
PHPAPI zend_string * php_session_create_id(PS_CREATE_SID_ARGS)
#define PS_CREATE_SID_FUNC(x)
zend_string_release_ex(func->internal_function.function_name, 0)
struct _zend_string zend_string
ZEND_RESULT_CODE zend_result