⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_mm.c

📁 php-4.4.7学习linux时下载的源代码
💻 C
字号:
/*    +----------------------------------------------------------------------+   | PHP Version 4                                                        |   +----------------------------------------------------------------------+   | Copyright (c) 1997-2007 The PHP Group                                |   +----------------------------------------------------------------------+   | This source file is subject to version 3.01 of the PHP license,      |   | that is bundled with this package in the file LICENSE, and is        |   | available through the world-wide-web at the following url:           |   | http://www.php.net/license/3_01.txt                                  |   | If you did not receive a copy of the PHP license and are unable to   |   | obtain it through the world-wide-web, please send a note to          |   | license@php.net so we can mail you a copy immediately.               |   +----------------------------------------------------------------------+   | Author: Sascha Schumann <sascha@schumann.cx>                         |   +----------------------------------------------------------------------+ *//* $Id: mod_mm.c,v 1.39.4.4.2.2 2007/01/01 09:46:46 sebastian Exp $ */#include "php.h"#ifdef HAVE_LIBMM#include <unistd.h>#include <mm.h>#include <time.h>#include <sys/stat.h>#include <sys/types.h>#include <fcntl.h>#include "php_session.h"#include "mod_mm.h"#include "SAPI.h"#ifdef ZTS# error mm is not thread-safe#endif#define PS_MM_FILE "session_mm_"/* For php_uint32 */#include "ext/standard/basic_functions.h"/* * this list holds all data associated with one session  */typedef struct ps_sd {	struct ps_sd *next;	php_uint32 hv;		/* hash value of key */	time_t ctime;		/* time of last change */	void *data;	size_t datalen;		/* amount of valid data */	size_t alloclen;	/* amount of allocated memory for data */	char key[1];		/* inline key */} ps_sd;typedef struct {	MM *mm;	ps_sd **hash;	php_uint32 hash_max;	php_uint32 hash_cnt;	pid_t owner;} ps_mm;static ps_mm *ps_mm_instance = NULL;#if 0#define ps_mm_debug(a) printf a#else#define ps_mm_debug(a)#endifstatic inline php_uint32 ps_sd_hash(const char *data, int len){	php_uint32 h;	const char *e = data + len;		for (h = 2166136261U; data < e; ) {		h *= 16777619;		h ^= *data++;	}		return h;}static void hash_split(ps_mm *data){	php_uint32 nmax;	ps_sd **nhash;	ps_sd **ohash, **ehash;	ps_sd *ps, *next;		nmax = ((data->hash_max + 1) << 1) - 1;	nhash = mm_calloc(data->mm, nmax + 1, sizeof(*data->hash));		if (!nhash) {		/* no further memory to expand hash table */		return;	}	ehash = data->hash + data->hash_max + 1;	for (ohash = data->hash; ohash < ehash; ohash++) {		for (ps = *ohash; ps; ps = next) {			next = ps->next;			ps->next = nhash[ps->hv & nmax];			nhash[ps->hv & nmax] = ps;		}	}	mm_free(data->mm, data->hash);	data->hash = nhash;	data->hash_max = nmax;}static ps_sd *ps_sd_new(ps_mm *data, const char *key){	php_uint32 hv, slot;	ps_sd *sd;	int keylen;		keylen = strlen(key);		sd = mm_malloc(data->mm, sizeof(ps_sd) + keylen);	if (!sd) {		TSRMLS_FETCH();		php_error_docref(NULL TSRMLS_CC, E_WARNING, "mm_malloc failed, avail %d, err %s", mm_available(data->mm), mm_error());		return NULL;	}	hv = ps_sd_hash(key, keylen);	slot = hv & data->hash_max;		sd->ctime = 0;	sd->hv = hv;	sd->data = NULL;	sd->alloclen = sd->datalen = 0;		memcpy(sd->key, key, keylen + 1);		sd->next = data->hash[slot];	data->hash[slot] = sd;	data->hash_cnt++;		if (!sd->next) {		if (data->hash_cnt >= data->hash_max)			hash_split(data);	}		ps_mm_debug(("inserting %s(%p) into slot %d\n", key, sd, slot));	return sd;}static void ps_sd_destroy(ps_mm *data, ps_sd *sd){	php_uint32 slot;	slot = ps_sd_hash(sd->key, strlen(sd->key)) & data->hash_max;	if (data->hash[slot] == sd)		data->hash[slot] = sd->next;	else {		ps_sd *prev;		/* There must be some entry before the one we want to delete */		for (prev = data->hash[slot]; prev->next != sd; prev = prev->next);		prev->next = sd->next;	}			data->hash_cnt--;	if (sd->data) 		mm_free(data->mm, sd->data);	mm_free(data->mm, sd);}static ps_sd *ps_sd_lookup(ps_mm *data, const char *key, int rw){	php_uint32 hv, slot;	ps_sd *ret, *prev;	hv = ps_sd_hash(key, strlen(key));	slot = hv & data->hash_max;		for (prev = NULL, ret = data->hash[slot]; ret; prev = ret, ret = ret->next)		if (ret->hv == hv && !strcmp(ret->key, key)) 			break;		if (ret && rw && ret != data->hash[slot]) {		/* Move the entry to the top of the linked list */				if (prev)			prev->next = ret->next;		ret->next = data->hash[slot];		data->hash[slot] = ret;	}	ps_mm_debug(("lookup(%s): ret=%p,hv=%u,slot=%d\n", key, ret, hv, slot));		return ret;}ps_module ps_mod_mm = {	PS_MOD(mm)};#define PS_MM_DATA ps_mm *data = PS_GET_MOD_DATA()static int ps_mm_initialize(ps_mm *data, const char *path){	data->owner = getpid();	data->mm = mm_create(0, path);	if (!data->mm) {		return FAILURE;	}	data->hash_cnt = 0;	data->hash_max = 511;	data->hash = mm_calloc(data->mm, data->hash_max + 1, sizeof(ps_sd *));	if (!data->hash) {		mm_destroy(data->mm);		return FAILURE;	}	return SUCCESS;}static void ps_mm_destroy(ps_mm *data){	int h;	ps_sd *sd, *next;	/* This function is called during each module shutdown,	   but we must not release the shared memory pool, when	   an Apache child dies! */	if (data->owner != getpid()) return;	for (h = 0; h < data->hash_max + 1; h++)		for (sd = data->hash[h]; sd; sd = next) {			next = sd->next;			ps_sd_destroy(data, sd);		}		mm_free(data->mm, data->hash);	mm_destroy(data->mm);	free(data);}PHP_MINIT_FUNCTION(ps_mm){	int save_path_len = strlen(PS(save_path));	int mod_name_len = strlen(sapi_module.name);	char *ps_mm_path, euid[30];	int ret;	ps_mm_instance = calloc(sizeof(*ps_mm_instance), 1);   	if (!ps_mm_instance)		return FAILURE;	if (!sprintf(euid,"%d", geteuid())) 		return FAILURE;		    /* Directory + '/' + File + Module Name + Effective UID + \0 */		ps_mm_path = emalloc(save_path_len+1+sizeof(PS_MM_FILE)+mod_name_len+strlen(euid)+1);		memcpy(ps_mm_path, PS(save_path), save_path_len + 1);	if (save_path_len > 0 && ps_mm_path[save_path_len - 1] != DEFAULT_SLASH) {		ps_mm_path[save_path_len] = DEFAULT_SLASH;		ps_mm_path[save_path_len+1] = '\0';	}	strcat(ps_mm_path, PS_MM_FILE);	strcat(ps_mm_path, sapi_module.name);	strcat(ps_mm_path, euid);		ret = ps_mm_initialize(ps_mm_instance, ps_mm_path);			efree(ps_mm_path);   	if (ret != SUCCESS) {		free(ps_mm_instance);		ps_mm_instance = NULL;		return FAILURE;	}		php_session_register_module(&ps_mod_mm);	return SUCCESS;}PHP_MSHUTDOWN_FUNCTION(ps_mm){	if (ps_mm_instance) {		ps_mm_destroy(ps_mm_instance);		return SUCCESS;	}	return FAILURE;}PS_OPEN_FUNC(mm){	ps_mm_debug(("open: ps_mm_instance=%p\n", ps_mm_instance));		if (!ps_mm_instance)		return FAILURE;		PS_SET_MOD_DATA(ps_mm_instance);		return SUCCESS;}PS_CLOSE_FUNC(mm){	PS_SET_MOD_DATA(NULL);	return SUCCESS;}PS_READ_FUNC(mm){	PS_MM_DATA;	ps_sd *sd;	int ret = FAILURE;	mm_lock(data->mm, MM_LOCK_RD);		sd = ps_sd_lookup(data, key, 0);	if (sd) {		*vallen = sd->datalen;		*val = emalloc(sd->datalen + 1);		memcpy(*val, sd->data, sd->datalen);		(*val)[sd->datalen] = '\0';		ret = SUCCESS;	}	mm_unlock(data->mm);		return ret;}PS_WRITE_FUNC(mm){	PS_MM_DATA;	ps_sd *sd;	mm_lock(data->mm, MM_LOCK_RW);	sd = ps_sd_lookup(data, key, 1);	if (!sd) {		sd = ps_sd_new(data, key);		ps_mm_debug(("new entry for %s\n", key));	}	if (sd) {		if (vallen >= sd->alloclen) {			if (data->mm) 				mm_free(data->mm, sd->data);			sd->alloclen = vallen + 1;			sd->data = mm_malloc(data->mm, sd->alloclen);			if (!sd->data) {				ps_sd_destroy(data, sd);				php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot allocate new data segment");				sd = NULL;			}		}		if (sd) {			sd->datalen = vallen;			memcpy(sd->data, val, vallen);			time(&sd->ctime);		}	}	mm_unlock(data->mm);		return sd ? SUCCESS : FAILURE;}PS_DESTROY_FUNC(mm){	PS_MM_DATA;	ps_sd *sd;		mm_lock(data->mm, MM_LOCK_RW);		sd = ps_sd_lookup(data, key, 0);	if (sd)		ps_sd_destroy(data, sd);		mm_unlock(data->mm);		return SUCCESS;}PS_GC_FUNC(mm) {	PS_MM_DATA;	time_t limit;	ps_sd **ohash, **ehash;	ps_sd *sd, *next;		*nrdels = 0;	ps_mm_debug(("gc\n"));			time(&limit);	limit -= maxlifetime;	mm_lock(data->mm, MM_LOCK_RW);	ehash = data->hash + data->hash_max + 1;	for (ohash = data->hash; ohash < ehash; ohash++)		for (sd = *ohash; sd; sd = next) {			next = sd->next;			if (sd->ctime < limit) {				ps_mm_debug(("purging %s\n", sd->key));				ps_sd_destroy(data, sd);				(*nrdels)++;			}		}	mm_unlock(data->mm);		return SUCCESS;}#endif/* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: sw=4 ts=4 fdm=marker * vim<600: sw=4 ts=4 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -