package.xml0000664000175000017500000002630014157324055014272 0ustar huixinchenhuixinchen yac pecl.php.net lockless user data cache yac is a fast, lock-free, shared memory user data cache for PHP. it can be used to replace APC or local memcached. Xinchen Hui laruence laruence@php.net yes 2021-12-18 2.3.1 2.3.1 stable stable PHP - PHP8.1 Supports 7.0.0 1.4.0 yac 2021-12-18 2.3.1 2.3.1 stable stable PHP License - PHP8.1 Supports 2021-01-06 2.3.0 2.3.0 stable stable PHP License - PHP8 Supported 2020-03-31 2.2.1 2.2.1 stable stable PHP License - Refactor key manipulation, avoding memory allocation - Refactor Yac::__set/__get by using native objects_handler 2020-03-31 2.2.0 2.2.0 stable stable PHP License - Added json serializer - Added igbinary serializer - change yac.serilalizer to string, "php", "json" etc 2020-03-27 2.1.2 2.1.2 stable stable PHP License - Fixed compiler warning of redefinition of macros - Fixed crc32c only pick the first byte - Also use crc32_u32 in 64 bits 2020-03-25 2.1.1 2.1.1 stable stable PHP License - Fixed Build in 32bits 2020-03-25 2.1.0 2.1.0 stable stable PHP License - Implemnented CAS based lock-free protection - Use SSE4.2 _mm_crc32 instead of normal crc32 to make speedup - Some optimization to avoding memory usage 2020-03-19 2.0.4 2.0.4 beta beta PHP License - Fixed PHP-7.4 windows build 2020-01-06 2.0.3 2.0.3 beta beta PHP License - Fixed PHP-7.4 Compatiblity 2017-07-27 2.0.2 2.0.2 beta beta PHP License - Fixed PHP-7.2 Compatiblity 2016-07-02 2.0.1 2.0.1 beta beta PHP License - Fixed issue #63 (include smart_str.h) 2015-10-27 2.0.0 2.0.0 beta beta PHP License - Release yac for PHP7 2014-10-22 0.9.2 0.9.2 beta beta PHP License - Add --with-system-fastlz option 2014-07-25 0.9.1 0.9.1 beta beta PHP License - Try to fix windows build 2014-07-24 0.9.0 0.9.0 beta beta PHP License - first release yac-2.3.1/storage/allocator/allocators/createfilemapping.c0000664000175000017500000002267614157324055025016 0ustar huixinchenhuixinchen/* +----------------------------------------------------------------------+ | Yet Another Cache | +----------------------------------------------------------------------+ | Copyright (c) 2013-2013 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. | +----------------------------------------------------------------------+ | Authors: Xinchen Hui | | Dmitry Stogov | | Wei Dai | +----------------------------------------------------------------------+ */ #include "php.h" #include "php_yac.h" #include "storage/yac_storage.h" #include "storage/allocator/yac_allocator.h" #include #include #include #define ACCEL_FILEMAP_NAME "Yac.SharedMemoryArea" #define ACCEL_FILEMAP_BASE "Yac.MemoryBase" #define MAX_MAP_RETRIES 25 static HANDLE memfile = NULL; static void *mapping_base; typedef struct { yac_shared_segment common; unsigned long size; } yac_shared_segment_create_file; #ifdef USE_FILE_MAPPING static char *create_name_with_username(char *name) /* {{{ */ { static char newname[MAXPATHLEN + UNLEN + 4]; char uname[UNLEN + 1]; DWORD unsize = UNLEN; GetUserName(uname, &unsize); snprintf(newname, sizeof(newname) - 1, "%s@%s", name, uname); return newname; } /* }}} */ static char *get_mmap_base_file(void) /* {{{ */ { static char windir[MAXPATHLEN+UNLEN + 3 + sizeof("\\\\@")]; char uname[UNLEN + 1]; DWORD unsize = UNLEN; int l; GetTempPath(MAXPATHLEN, windir); GetUserName(uname, &unsize); l = strlen(windir); snprintf(windir + l, sizeof(windir) - l - 1, "\\%s@%s", ACCEL_FILEMAP_BASE, uname); return windir; } /* }}} */ static int yac_shared_alloc_reattach(size_t requested_size, char **error_in) /* {{{ */ { void *wanted_mapping_base; char *mmap_base_file = get_mmap_base_file(); FILE *fp = fopen(mmap_base_file, "r"); MEMORY_BASIC_INFORMATION info; if (!fp) { *error_in="fopen"; return ALLOC_FAILURE; } if (!fscanf(fp, "%p", &wanted_mapping_base)) { *error_in="read mapping base"; fclose(fp); return ALLOC_FAILURE; } fclose(fp); /* Check if the requested address space is free */ if (VirtualQuery(wanted_mapping_base, &info, sizeof(info)) == 0) { *error_in="VirtualQuery"; return ALLOC_FAILURE; } if (info.State != MEM_FREE) { *error_in="info.State"; return ALLOC_FAILURE; } if (info.RegionSize < requested_size) { *error_in="info.RegionSize"; return ALLOC_FAILURE; } mapping_base = MapViewOfFileEx(memfile, FILE_MAP_ALL_ACCESS, 0, 0, 0, wanted_mapping_base); if (mapping_base == NULL) { return ALLOC_FAIL_MAPPING; } return SUCCESSFULLY_REATTACHED; } /* }}} */ static int create_segments(unsigned long k_size, unsigned long v_size, yac_shared_segment_create_file **shared_segments_p, int *shared_segments_count, char **error_in) /* {{{ */ { int ret; unsigned long allocate_size, occupied_size = 0; unsigned int i, segment_size, segments_num = 1024, is_reattach = 0; int map_retries = 0; yac_shared_segment_create_file first_segment; void *default_mapping_base_set[] = {0, 0}; /* TODO: improve fixed addresses on x64. It still makes no sense to do it as Windows addresses are virtual per se and can or should be randomized anyway through Address Space Layout Radomization (ASLR). We can still let the OS do its job and be sure that each process gets the same address if desired. Not done yet, @zend refused but did not remember the exact reason, pls add info here if one of you know why :) */ #if defined(_WIN64) void *vista_mapping_base_set[] = { (void *) 0x0000100000000000, (void *) 0x0000200000000000, (void *) 0x0000300000000000, (void *) 0x0000700000000000, 0 }; #else void *vista_mapping_base_set[] = { (void *) 0x20000000, (void *) 0x21000000, (void *) 0x30000000, (void *) 0x31000000, (void *) 0x50000000, 0 }; #endif void **wanted_mapping_base = default_mapping_base_set; k_size = YAC_SMM_ALIGNED_SIZE(k_size); v_size = YAC_SMM_ALIGNED_SIZE(v_size); while ((v_size / segments_num) < YAC_SMM_SEGMENT_MIN_SIZE) { segments_num >>= 1; } segment_size = v_size / segments_num; ++segments_num; allocate_size = k_size + v_size; /* Mapping retries: When Apache2 restarts, the parent process startup routine can be called before the child process is killed. In this case, the map will fail and we have to sleep some time (until the child releases the mapping object) and retry.*/ do { memfile = OpenFileMapping(FILE_MAP_WRITE, 0, create_name_with_username(ACCEL_FILEMAP_NAME)); if (memfile == NULL) { break; } ret = yac_shared_alloc_reattach((size_t)k_size, error_in); if (ret == ALLOC_FAIL_MAPPING) { /* Mapping failed, wait for mapping object to get freed and retry */ CloseHandle(memfile); memfile = NULL; Sleep(1000 * (map_retries + 1)); } else if (ret == SUCCESSFULLY_REATTACHED) { is_reattach = 1; break; } else { return ret; } } while (++map_retries < MAX_MAP_RETRIES); if (map_retries == MAX_MAP_RETRIES) { *error_in = "OpenFileMapping"; return 0; } *shared_segments_p = (yac_shared_segment_create_file *)calloc(1, segments_num * sizeof(yac_shared_segment_create_file)); if(!*shared_segments_p) { *error_in = "calloc"; return 0; } *shared_segments_count = segments_num; /* Starting from windows Vista, heap randomization occurs which might cause our mapping base to be taken (fail to map). So under Vista, we try to map into a hard coded predefined addresses in high memory. */ if (!YAC_G(mmap_base) || !*YAC_G(mmap_base)) { do { OSVERSIONINFOEX osvi; SYSTEM_INFO si; ZeroMemory(&si, sizeof(SYSTEM_INFO)); ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); if (! GetVersionEx ((OSVERSIONINFO *) &osvi)) { osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (!GetVersionEx((OSVERSIONINFO *)&osvi)) { break; } } GetSystemInfo(&si); /* Are we running Vista ? */ if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion == 6) { wanted_mapping_base = vista_mapping_base_set; } } while (0); } else { char *s = YAC_G(mmap_base); /* skip leading 0x, %p assumes hexdeciaml format anyway */ if (*s == '0' && *(s + 1) == 'x') { s += 2; } if (sscanf(s, "%p", &default_mapping_base_set[0]) != 1) { *error_in = "mapping"; return 0; } } if (is_reattach == 0) { memfile = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, allocate_size, create_name_with_username(ACCEL_FILEMAP_NAME)); if (memfile == NULL) { *error_in = "CreateFileMapping"; return 0; } do { first_segment.common.p = mapping_base = MapViewOfFileEx(memfile, FILE_MAP_ALL_ACCESS, 0, 0, 0, *wanted_mapping_base); if (wanted_mapping_base == NULL) { break; } *wanted_mapping_base++; } while (!mapping_base); } if(mapping_base == NULL) { *error_in = "MapViewOfFileEx"; return 0; } else { char *mmap_base_file = get_mmap_base_file(); FILE *fp = fopen(mmap_base_file, "w"); if (!fp) { *error_in = "get_mmap_base_file"; return 0; } fprintf(fp, "%p", mapping_base); fclose(fp); } first_segment.common.p = mapping_base; first_segment.size = allocate_size; first_segment.common.size = k_size; first_segment.common.pos = 0; (*shared_segments_p)[0] = first_segment; occupied_size = k_size; for (i = 1; i < segments_num; i++) { (*shared_segments_p)[i].size = 0; (*shared_segments_p)[i].common.pos = 0; (*shared_segments_p)[i].common.p = (void *)((char *)first_segment.common.p + occupied_size); if ((allocate_size - occupied_size) >= YAC_SMM_ALIGNED_SIZE(segment_size)) { (*shared_segments_p)[i].common.size = YAC_SMM_ALIGNED_SIZE(segment_size); occupied_size += YAC_SMM_ALIGNED_SIZE(segment_size); } else { (*shared_segments_p)[i].common.size = (allocate_size - occupied_size); break; } } return 1; } /* }}} */ static int detach_segment(yac_shared_segment *shared_segment) /* {{{ */ { if (!shared_segment->size && mapping_base) { UnmapViewOfFile(mapping_base); CloseHandle(memfile); } return 0; } /* }}} */ static unsigned long segment_type_size(void) /* {{{ */ { return sizeof(yac_shared_segment_create_file); } /* }}} */ yac_shared_memory_handlers yac_alloc_create_file_handlers = /* {{{ */ { (create_segments_t)create_segments, detach_segment, segment_type_size }; /* }}} */ #endif /* USE_CREATE_FILE */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ yac-2.3.1/storage/allocator/allocators/mmap.c0000664000175000017500000000755214157324055022265 0ustar huixinchenhuixinchen/* +----------------------------------------------------------------------+ | Yet Another Cache | +----------------------------------------------------------------------+ | Copyright (c) 2013-2013 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. | +----------------------------------------------------------------------+ | Authors: Xinchen Hui | +----------------------------------------------------------------------+ */ #include "storage/yac_storage.h" #include "storage/allocator/yac_allocator.h" #ifdef USE_MMAP #include #include #include #include #include #if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) # define MAP_ANONYMOUS MAP_ANON #endif #ifndef MAP_FAILED #define MAP_FAILED (void *)-1 #endif typedef struct { yac_shared_segment common; unsigned long size; } yac_shared_segment_mmap; static int create_segments(unsigned long k_size, unsigned long v_size, yac_shared_segment_mmap **shared_segments_p, int *shared_segments_count, char **error_in) /* {{{ */ { unsigned long allocate_size, occupied_size = 0; unsigned int i, segment_size, segments_num = 1024; yac_shared_segment_mmap first_segment; k_size = YAC_SMM_ALIGNED_SIZE(k_size); v_size = YAC_SMM_ALIGNED_SIZE(v_size); while ((v_size / segments_num) < YAC_SMM_SEGMENT_MIN_SIZE) { segments_num >>= 1; } segment_size = v_size / segments_num; ++segments_num; allocate_size = k_size + v_size; first_segment.common.p = mmap(0, allocate_size, PROT_READ | PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); if (first_segment.common.p == MAP_FAILED) { *error_in = "mmap"; return 0; } first_segment.size = allocate_size; first_segment.common.size = k_size; first_segment.common.pos = 0; *shared_segments_p = (yac_shared_segment_mmap *)calloc(1, segments_num * sizeof(yac_shared_segment_mmap)); if (!*shared_segments_p) { munmap(first_segment.common.p, first_segment.size); *error_in = "calloc"; return 0; } else { *shared_segments_p[0] = first_segment; } *shared_segments_count = segments_num; occupied_size = k_size; for (i = 1; i < segments_num; i++) { (*shared_segments_p)[i].size = 0; (*shared_segments_p)[i].common.pos = 0; (*shared_segments_p)[i].common.p = first_segment.common.p + occupied_size; if ((allocate_size - occupied_size) >= YAC_SMM_ALIGNED_SIZE(segment_size)) { (*shared_segments_p)[i].common.size = YAC_SMM_ALIGNED_SIZE(segment_size); occupied_size += YAC_SMM_ALIGNED_SIZE(segment_size); } else { (*shared_segments_p)[i].common.size = (allocate_size - occupied_size); break; } } return 1; } /* }}} */ static int detach_segment(yac_shared_segment *shared_segment) /* {{{ */ { if (shared_segment->size) { munmap(shared_segment->p, shared_segment->size); } return 0; } /* }}} */ static unsigned long segment_type_size(void) /* {{{ */ { return sizeof(yac_shared_segment_mmap); } /* }}} */ yac_shared_memory_handlers yac_alloc_mmap_handlers = /* {{{ */ { (create_segments_t)create_segments, detach_segment, segment_type_size }; /* }}} */ #endif /* USE_MMAP */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ yac-2.3.1/storage/allocator/allocators/shm.c0000664000175000017500000001415414157324055022116 0ustar huixinchenhuixinchen/* +----------------------------------------------------------------------+ | Yet Another Cache | +----------------------------------------------------------------------+ | Copyright (c) 2013-2013 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. | +----------------------------------------------------------------------+ | Authors: Xinchen Hui | +----------------------------------------------------------------------+ */ #include "storage/yac_storage.h" #include "storage/allocator/yac_allocator.h" #ifdef USE_SHM #if defined(__FreeBSD__) # include #endif #include #include #include #include #include #include #include #include #include #include #include typedef struct { yac_shared_segment common; int shm_id; } yac_shared_segment_shm; static int create_segments(size_t k_size, size_t v_size, yac_shared_segment_shm **shared_segments_p, int *shared_segments_count, char **error_in) /* {{{ */ { struct shmid_ds sds; int shm_id, shmget_flags; yac_shared_segment_shm *shared_segments, first_segment; unsigned int i, j, allocate_size, allocated_num, segments_num, segment_size; shmget_flags = IPC_CREAT|SHM_R|SHM_W|IPC_EXCL; segments_num = 1024; while ((v_size / segments_num) < YAC_SMM_SEGMENT_MIN_SIZE) { segments_num >>= 1; } segment_size = v_size / segments_num; allocate_size = YAC_SMM_SEGMENT_MAX_SIZE; while ((shm_id = shmget(IPC_PRIVATE, allocate_size, shmget_flags)) < 0) { allocate_size >>= 1; } if (shm_id < 0) { /* this should never happen */ *error_in = "shmget"; return 0; } if (allocate_size < YAC_SMM_SEGMENT_MIN_SIZE) { /* this should never happen */ *error_in = "shmget"; return 0; } if (k_size <= allocate_size) { first_segment.shm_id = shm_id; first_segment.common.pos = 0; first_segment.common.size = allocate_size; first_segment.common.p = shmat(shm_id, NULL, 0); shmctl(shm_id, IPC_RMID, &sds); if (first_segment.common.p == (void *)-1) { *error_in = "shmat"; return 0; } } else { shmctl(shm_id, IPC_RMID, &sds); *error_in = "shmget"; return 0; } allocated_num = (v_size % allocate_size)? (v_size / allocate_size) + 1 : (v_size / allocate_size); shared_segments = (yac_shared_segment_shm *)calloc(1, (allocated_num) * sizeof(yac_shared_segment_shm)); if (!shared_segments) { *error_in = "calloc"; return 0; } for (i = 0; i < allocated_num; i ++) { shm_id = shmget(IPC_PRIVATE, allocate_size, shmget_flags); if (shm_id == -1) { *error_in = "shmget"; for (j = 0; j < i; j++) { shmdt(shared_segments[j].common.p); } free(shared_segments); return 0; } shared_segments[i].shm_id = shm_id; shared_segments[i].common.pos = 0; shared_segments[i].common.size = allocate_size; shared_segments[i].common.p = shmat(shm_id, NULL, 0); shmctl(shm_id, IPC_RMID, &sds); if (shared_segments[i].common.p == (void *)-1) { *error_in = "shmat"; for (j = 0; j < i; j++) { shmdt(shared_segments[j].common.p); } free(shared_segments); return 0; } } ++segments_num; *shared_segments_p = (yac_shared_segment_shm *)calloc(1, segments_num * sizeof(yac_shared_segment_shm)); if (!*shared_segments_p) { free(shared_segments); *error_in = "calloc"; return 0; } else { *shared_segments_p[0] = first_segment; } *shared_segments_count = segments_num; j = 0; for (i = 1; i < segments_num; i++) { if (shared_segments[j].common.pos == 0) { (*shared_segments_p)[i].shm_id = shared_segments[j].shm_id; } if ((shared_segments[j].common.size - shared_segments[j].common.pos) >= (2 * YAC_SMM_ALIGNED_SIZE(segment_size))) { (*shared_segments_p)[i].common.pos = 0; (*shared_segments_p)[i].common.size = YAC_SMM_ALIGNED_SIZE(segment_size); (*shared_segments_p)[i].common.p = shared_segments[j].common.p + YAC_SMM_ALIGNED_SIZE(shared_segments[j].common.pos); shared_segments[j].common.pos += YAC_SMM_ALIGNED_SIZE(segment_size); } else { (*shared_segments_p)[i].common.pos = 0; (*shared_segments_p)[i].common.size = shared_segments[j].common.size - shared_segments[j].common.pos; (*shared_segments_p)[i].common.p = shared_segments[j].common.p + YAC_SMM_ALIGNED_SIZE(shared_segments[j].common.pos); j++; } } free(shared_segments); return 1; } /* }}} */ static int detach_segment(yac_shared_segment_shm *shared_segment) /* {{{ */ { if (shared_segment->shm_id) { shmdt(shared_segment->common.p); } return 1; } /* }}} */ static size_t segment_type_size(void) /* {{{ */ { return sizeof(yac_shared_segment_shm); } /* }}} */ yac_shared_memory_handlers yac_alloc_shm_handlers = /* {{{ */ { (create_segments_t)create_segments, (detach_segment_t)detach_segment, segment_type_size }; /* }}} */ #endif /* USE_SHM */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ yac-2.3.1/storage/allocator/yac_allocator.h0000664000175000017500000000754614157324055022014 0ustar huixinchenhuixinchen/* +----------------------------------------------------------------------+ | Yet Another Cache | +----------------------------------------------------------------------+ | Copyright (c) 2013-2013 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. | +----------------------------------------------------------------------+ | Authors: Xinchen Hui | +----------------------------------------------------------------------+ */ #ifndef YAC_ALLOCATOR_H #define YAC_ALLOCATOR_H #ifdef HAVE_CONFIG_H #include "config.h" #endif #define YAC_SMM_ALIGNMENT 8 #define YAC_SMM_ALIGNMENT_LOG2 3 #define YAC_SMM_ALIGNMENT_MASK ~(YAC_SMM_ALIGNMENT - 1) #define YAC_SMM_BLOCK_HEADER_SIZE YAC_SMM_ALIGNED_SIZE(sizeof(yac_shared_block_header)) #define YAC_SMM_MAIN_SEG_SIZE (4*1024*1024) #define YAC_SMM_SEGMENT_MAX_SIZE (32*1024*1024) #define YAC_SMM_SEGMENT_MIN_SIZE (4*1024*1024) #define YAC_SMM_MIN_BLOCK_SIZE 128 #define YAC_SMM_ALIGNED_SIZE(x) (((x) + YAC_SMM_ALIGNMENT - 1) & YAC_SMM_ALIGNMENT_MASK) #define YAC_SMM_TRUE_SIZE(x) ((x < YAC_SMM_MIN_BLOCK_SIZE)? (YAC_SMM_MIN_BLOCK_SIZE) : (YAC_SMM_ALIGNED_SIZE(x))) #ifdef PHP_WIN32 # define USE_FILE_MAPPING 1 # define inline __inline #elif defined(HAVE_SHM_MMAP_ANON) # define USE_MMAP 1 #elif defined(HAVE_SHM_IPC) # define USE_SHM 1 #else #error(no builtin shared memory supported) #endif #define ALLOC_FAILURE 0 #define ALLOC_SUCCESS 1 #define FAILED_REATTACHED 2 #define SUCCESSFULLY_REATTACHED 4 #define ALLOC_FAIL_MAPPING 8 typedef int (*create_segments_t)(unsigned long k_size, unsigned long v_size, yac_shared_segment **shared_segments, int *shared_segment_count, char **error_in); typedef int (*detach_segment_t)(yac_shared_segment *shared_segment); typedef struct { create_segments_t create_segments; detach_segment_t detach_segment; unsigned long (*segment_type_size)(void); } yac_shared_memory_handlers; typedef struct { const char *name; yac_shared_memory_handlers *handler; } yac_shared_memory_handler_entry; int yac_allocator_startup(unsigned long first_seg_size, unsigned long size, char **err); void yac_allocator_shutdown(void); unsigned long yac_allocator_real_size(unsigned long size); void *yac_allocator_raw_alloc(unsigned long real_size, int seg); int yac_allocator_free(void *p); static inline void * yac_allocator_alloc(unsigned long size, int seg) { unsigned long real_size = yac_allocator_real_size(size); if (!real_size) { return (void *)0; } return yac_allocator_raw_alloc(real_size, seg); } #if defined(USE_MMAP) extern yac_shared_memory_handlers yac_alloc_mmap_handlers; #define yac_shared_memory_handler yac_alloc_mmap_handlers #define YAC_SHARED_MEMORY_HANDLER_NAME "mmap" #elif defined(USE_SHM) extern yac_shared_memory_handlers yac_alloc_shm_handlers; #define yac_shared_memory_handler yac_alloc_shm_handlers #define YAC_SHARED_MEMORY_HANDLER_NAME "shm" #elif defined(USE_FILE_MAPPING) extern yac_shared_memory_handlers yac_alloc_create_file_handlers; #define yac_shared_memory_handler yac_alloc_create_file_handlers #define YAC_SHARED_MEMORY_HANDLER_NAME "file_mapping" #endif #endif /* YAC_ALLOCATOR_H */ yac-2.3.1/storage/allocator/yac_allocator.c0000664000175000017500000001344414157324055022001 0ustar huixinchenhuixinchen/* +----------------------------------------------------------------------+ | Yet Another Cache | +----------------------------------------------------------------------+ | Copyright (c) 2013-2013 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. | +----------------------------------------------------------------------+ | Authors: Xinchen Hui | +----------------------------------------------------------------------+ */ #include #include #include #include "php.h" #include "storage/yac_storage.h" #include "yac_allocator.h" int yac_allocator_startup(unsigned long k_size, unsigned long size, char **msg) /* {{{ */ { char *p; yac_shared_segment *segments = NULL; int i, segments_num, segments_array_size, segment_size; const yac_shared_memory_handlers *he; if ((he = &yac_shared_memory_handler)) { int ret = he->create_segments(k_size, size, &segments, &segments_num, msg); if (!ret) { if (segments) { int i; for (i = 0; i < segments_num; i++) { if (segments[i].p && segments[i].p != (void *)-1) { he->detach_segment(&segments[i]); } } free(segments); } return 0; } } else { return 0; } segment_size = he->segment_type_size(); segments_array_size = (segments_num - 1) * segment_size; yac_storage = segments[0].p; memcpy(&YAC_SG(first_seg), (char *)(&segments[0]), segment_size); YAC_SG(segments_num) = segments_num - 1; YAC_SG(segments_num_mask) = YAC_SG(segments_num) - 1; YAC_SG(segments) = (yac_shared_segment **)((char *)yac_storage + YAC_SMM_ALIGNED_SIZE(sizeof(yac_storage_globals) + segment_size - sizeof(yac_shared_segment))); p = (char *)YAC_SG(segments) + (sizeof(void *) * YAC_SG(segments_num)); memcpy(p, (char *)segments + segment_size, segments_array_size); for (i = 0; i < YAC_SG(segments_num); i++) { YAC_SG(segments)[i] = (yac_shared_segment *)p; p += segment_size; } YAC_SG(slots) = (yac_kv_key *)((char *)YAC_SG(segments) + (YAC_SG(segments_num) * sizeof(void *)) + YAC_SMM_ALIGNED_SIZE(segments_array_size)); free(segments); return 1; } /* }}} */ void yac_allocator_shutdown(void) /* {{{ */ { yac_shared_segment **segments; const yac_shared_memory_handlers *he; segments = YAC_SG(segments); if (segments) { if ((he = &yac_shared_memory_handler)) { int i = 0; for (i = 0; i < YAC_SG(segments_num); i++) { he->detach_segment(segments[i]); } he->detach_segment(&YAC_SG(first_seg)); } } } /* }}} */ static inline void *yac_allocator_alloc_algo2(unsigned long size, int hash) /* {{{ */ { yac_shared_segment *segment; unsigned int seg_size, retry, pos, current; current = hash & YAC_SG(segments_num_mask); /* do we really need lock here? it depends the real life exam */ retry = 3; do_retry: segment = YAC_SG(segments)[current]; seg_size = segment->size; pos = segment->pos; if ((seg_size - pos) >= size) { do_alloc: pos += size; segment->pos = pos; if (segment->pos == pos) { return (void *)((char *)segment->p + (pos - size)); } else if (retry--) { goto do_retry; } return NULL; } else { int i, max; max = (YAC_SG(segments_num) > 4)? 4 : YAC_SG(segments_num); for (i = 1; i < max; i++) { segment = YAC_SG(segments)[(current + i) & YAC_SG(segments_num_mask)]; seg_size = segment->size; pos = segment->pos; if ((seg_size - pos) >= size) { current = (current + i) & YAC_SG(segments_num_mask); goto do_alloc; } } segment->pos = 0; pos = 0; ++YAC_SG(recycles); goto do_alloc; } } /* }}} */ #if 0 static inline void *yac_allocator_alloc_algo1(unsigned long size) /* {{{ */ { int i, j, picked_seg, atime; picked_seg = (YAC_SG(current_seg) + 1) & YAC_SG(segments_num_mask); atime = YAC_SG(segments)[picked_seg]->atime; for (i = 0; i < 10; i++) { j = (picked_seg + 1) & YAC_SG(segments_num_mask); if (YAC_SG(segments)[j]->atime < atime) { picked_seg = j; atime = YAC_SG(segments)[j]->atime; } } YAC_SG(current_seg) = picked_seg; YAC_SG(segments)[picked_seg]->pos = 0; return yac_allocator_alloc_algo2(size); } /* }}} */ #endif unsigned long yac_allocator_real_size(unsigned long size) /* {{{ */ { unsigned long real_size = YAC_SMM_TRUE_SIZE(size); if (real_size > YAC_SG(segments)[0]->size) { return 0; } return real_size; } /* }}} */ void * yac_allocator_raw_alloc(unsigned long real_size, int hash) /* {{{ */ { return yac_allocator_alloc_algo2(real_size, hash); /* if (YAC_SG(exhausted)) { return yac_allocator_alloc_algo1(real_size); } else { void *p; if ((p = yac_allocator_alloc_algo2(real_size))) { return p; } return yac_allocator_alloc_algo1(real_size); } */ } /* }}} */ #if 0 void yac_allocator_touch(void *p, unsigned long atime) /* {{{ */ { yac_shared_block_header h = *(yac_shared_block_header *)(p - sizeof(yac_shared_block_header)); if (h.seg >= YAC_SG(segments_num)) { return; } YAC_SG(segments)[h.seg]->atime = atime; } /* }}} */ #endif /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ yac-2.3.1/storage/yac_storage.h0000664000175000017500000001013214157324055017501 0ustar huixinchenhuixinchen/* +----------------------------------------------------------------------+ | Yet Another Cache | +----------------------------------------------------------------------+ | Copyright (c) 2013-2013 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: Xinchen Hui | +----------------------------------------------------------------------+ */ /* $Id$ */ #ifndef YAC_STORAGE_H #define YAC_STORAGE_H #define YAC_STORAGE_MAX_ENTRY_LEN (1 << 20) #define YAC_STORAGE_MAX_KEY_LEN (48) #define YAC_STORAGE_FACTOR (1.25) #define YAC_KEY_KLEN_MASK (255) #define YAC_KEY_VLEN_BITS (8) #define YAC_KEY_KLEN(k) ((k).len & YAC_KEY_KLEN_MASK) #define YAC_KEY_VLEN(k) ((k).len >> YAC_KEY_VLEN_BITS) #define YAC_KEY_SET_LEN(k, kl, vl) ((k).len = (vl << YAC_KEY_VLEN_BITS) | (kl & YAC_KEY_KLEN_MASK)) #define YAC_FULL_CRC_THRESHOLD 256 #define USER_ALLOC emalloc #define USER_FREE efree typedef struct { unsigned long atime; unsigned int len; char data[1]; } yac_kv_val; typedef struct { unsigned long h; unsigned int crc; unsigned int ttl; unsigned int len; unsigned int flag; unsigned int size; unsigned int mutex; yac_kv_val *val; unsigned char key[YAC_STORAGE_MAX_KEY_LEN]; } yac_kv_key; typedef struct _yac_item_list { unsigned int index; unsigned long h; unsigned long crc; unsigned int ttl; unsigned int k_len; unsigned int v_len; unsigned int flag; unsigned int size; unsigned char key[YAC_STORAGE_MAX_KEY_LEN]; struct _yac_item_list *next; } yac_item_list; typedef struct { volatile unsigned int pos; unsigned int size; void *p; } yac_shared_segment; typedef struct { unsigned long k_msize; unsigned long v_msize; unsigned int segments_num; unsigned int segment_size; unsigned int slots_num; unsigned int slots_size; unsigned int miss; unsigned int fails; unsigned int kicks; unsigned int recycles; unsigned long hits; } yac_storage_info; typedef struct { yac_kv_key *slots; unsigned int slots_mask; unsigned int slots_num; unsigned int slots_size; unsigned int miss; unsigned int fails; unsigned int kicks; unsigned int recycles; unsigned long hits; yac_shared_segment **segments; unsigned int segments_num; unsigned int segments_num_mask; yac_shared_segment first_seg; } yac_storage_globals; extern yac_storage_globals *yac_storage; #define YAC_SG(element) (yac_storage->element) int yac_storage_startup(unsigned long first_size, unsigned long size, char **err); void yac_storage_shutdown(void); int yac_storage_find(const char *key, unsigned int len, char **data, unsigned int *size, unsigned int *flag, int *cas, unsigned long tv); int yac_storage_update(const char *key, unsigned int len, char *data, unsigned int size, unsigned int falg, int ttl, int add, unsigned long tv); int yac_storage_delete(const char *key, unsigned int len, int ttl, unsigned long tv); void yac_storage_flush(void); const char * yac_storage_shared_memory_name(void); yac_storage_info * yac_storage_get_info(void); void yac_storage_free_info(yac_storage_info *info); yac_item_list * yac_storage_dump(unsigned int limit); void yac_storage_free_list(yac_item_list *list); #define yac_storage_exists(ht, key, len) yac_storage_find(ht, key, len, NULL) #endif /* YAC_STORAGE_H */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ yac-2.3.1/storage/yac_storage.c0000664000175000017500000005156714157324055017515 0ustar huixinchenhuixinchen/* +----------------------------------------------------------------------+ | Yet Another Cache | +----------------------------------------------------------------------+ | Copyright (c) 2013-2013 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: Xinchen Hui | +----------------------------------------------------------------------+ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #if HAVE_SSE_CRC32 #include "Zend/zend_cpuinfo.h" #include static uint32_t crc32c_sse42(const char *dagta, unsigned int size); #endif #include "yac_atomic.h" #include "yac_storage.h" #include "allocator/yac_allocator.h" yac_storage_globals *yac_storage; static uint32_t (*yac_crc)(const char *data, unsigned int size); static uint32_t crc32(const char *dagta, unsigned int size); static inline unsigned int yac_storage_align_size(unsigned int size) /* {{{ */ { int bits = 0; while ((size = size >> 1)) { ++bits; } return (1 << bits); } /* }}} */ int yac_storage_startup(unsigned long fsize, unsigned long size, char **msg) /* {{{ */ { unsigned long real_size; if (!yac_allocator_startup(fsize, size, msg)) { return 0; } #if HAVE_SSE_CRC32 if (zend_cpu_supports_sse42()) { yac_crc = crc32c_sse42; } else #endif { yac_crc = crc32; } size = YAC_SG(first_seg).size - ((char *)YAC_SG(slots) - (char *)yac_storage); real_size = yac_storage_align_size(size / sizeof(yac_kv_key)); if (!((size / sizeof(yac_kv_key)) & ~(real_size << 1))) { real_size <<= 1; } YAC_SG(slots_size) = real_size; YAC_SG(slots_mask) = real_size - 1; YAC_SG(slots_num) = 0; YAC_SG(fails) = 0; YAC_SG(hits) = 0; YAC_SG(miss) = 0; YAC_SG(kicks) = 0; memset((char *)YAC_SG(slots), 0, sizeof(yac_kv_key) * real_size); return 1; } /* }}} */ void yac_storage_shutdown(void) /* {{{ */ { yac_allocator_shutdown(); } /* }}} */ /* {{{ MurmurHash2 (Austin Appleby) */ static inline uint64_t yac_inline_hash_func1(const char *data, unsigned int len) { unsigned int h, k; h = 0 ^ len; while (len >= 4) { k = data[0]; k |= data[1] << 8; k |= data[2] << 16; k |= data[3] << 24; k *= 0x5bd1e995; k ^= k >> 24; k *= 0x5bd1e995; h *= 0x5bd1e995; h ^= k; data += 4; len -= 4; } switch (len) { case 3: h ^= data[2] << 16; case 2: h ^= data[1] << 8; case 1: h ^= data[0]; h *= 0x5bd1e995; } h ^= h >> 13; h *= 0x5bd1e995; h ^= h >> 15; return h; } /* }}} */ /* {{{ DJBX33A (Daniel J. Bernstein, Times 33 with Addition) * * This is Daniel J. Bernstein's popular `times 33' hash function as * posted by him years ago on comp->lang.c. It basically uses a function * like ``hash(i) = hash(i-1) * 33 + str[i]''. This is one of the best * known hash functions for strings. Because it is both computed very * fast and distributes very well. * * The magic of number 33, i.e. why it works better than many other * constants, prime or not, has never been adequately explained by * anyone. So I try an explanation: if one experimentally tests all * multipliers between 1 and 256 (as RSE did now) one detects that even * numbers are not useable at all. The remaining 128 odd numbers * (except for the number 1) work more or less all equally well. They * all distribute in an acceptable way and this way fill a hash table * with an average percent of approx. 86%. * * If one compares the Chi^2 values of the variants, the number 33 not * even has the best value. But the number 33 and a few other equally * good numbers like 17, 31, 63, 127 and 129 have nevertheless a great * advantage to the remaining numbers in the large set of possible * multipliers: their multiply operation can be replaced by a faster * operation based on just one shift plus either a single addition * or subtraction operation. And because a hash function has to both * distribute good _and_ has to be very fast to compute, those few * numbers should be preferred and seems to be the reason why Daniel J. * Bernstein also preferred it. * * * -- Ralf S. Engelschall */ static inline uint64_t yac_inline_hash_func2(const char *key, uint32_t len) { register uint64_t hash = 5381; /* variant with the hash unrolled eight times */ for (; len >= 8; len -= 8) { hash = ((hash << 5) + hash) + *key++; hash = ((hash << 5) + hash) + *key++; hash = ((hash << 5) + hash) + *key++; hash = ((hash << 5) + hash) + *key++; hash = ((hash << 5) + hash) + *key++; hash = ((hash << 5) + hash) + *key++; hash = ((hash << 5) + hash) + *key++; hash = ((hash << 5) + hash) + *key++; } switch (len) { case 7: hash = ((hash << 5) + hash) + *key++; /* fallthrough... */ case 6: hash = ((hash << 5) + hash) + *key++; /* fallthrough... */ case 5: hash = ((hash << 5) + hash) + *key++; /* fallthrough... */ case 4: hash = ((hash << 5) + hash) + *key++; /* fallthrough... */ case 3: hash = ((hash << 5) + hash) + *key++; /* fallthrough... */ case 2: hash = ((hash << 5) + hash) + *key++; /* fallthrough... */ case 1: hash = ((hash << 5) + hash) + *key++; break; case 0: break; default: break; } return hash; } /* }}} */ /* {{{ COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or * code or tables extracted from it, as desired without restriction. * * First, the polynomial itself and its table of feedback terms. The * polynomial is * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 * * Note that we take it "backwards" and put the highest-order term in * the lowest-order bit. The X^32 term is "implied"; the LSB is the * X^31 term, etc. The X^0 term (usually shown as "+1") results in * the MSB being 1 * * Note that the usual hardware shift register implementation, which * is what we're using (we're merely optimizing it by doing eight-bit * chunks at a time) shifts bits into the lowest-order term. In our * implementation, that means shifting towards the right. Why do we * do it this way? Because the calculated CRC must be transmitted in * order from highest-order term to lowest-order term. UARTs transmit * characters in order from LSB to MSB. By storing the CRC this way * we hand it to the UART in the order low-byte to high-byte; the UART * sends each low-bit to high-bit; and the result is transmission bit * by bit from highest- to lowest-order term without requiring any bit * shuffling on our part. Reception works similarly * * The feedback terms table consists of 256, 32-bit entries. Notes * * The table can be generated at runtime if desired; code to do so * is shown later. It might not be obvious, but the feedback * terms simply represent the results of eight shift/xor opera * tions for all combinations of data and CRC register values * * The values must be right-shifted by eight bits by the "updcrc * logic; the shift must be unsigned (bring in zeroes). On some * hardware you could probably optimize the shift in assembler by * using byte-swap instructions * polynomial $edb88320 * * * CRC32 code derived from work by Gary S. Brown. */ static unsigned int crc32_tab[] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; static uint32_t crc32(const char *buf, unsigned int size) { const char *p; uint32_t crc = 0 ^ 0xFFFFFFFF; p = buf; while (size--) { crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); } return crc ^ 0xFFFFFFFF; } /* }}} */ #if HAVE_SSE_CRC32 static uint32_t crc32c_sse42(const char *buf, unsigned int size) /* {{{ */ { uint32_t crc = 0 ^ 0xFFFFFFFF; #if __x86_64__ while (size >= sizeof(uint64_t)) { crc = _mm_crc32_u64(crc, *(uint64_t*)buf); buf += sizeof(uint64_t); size -= sizeof(uint64_t); } #endif while (size >= sizeof(uint32_t)) { crc = _mm_crc32_u32(crc, *(uint32_t*)buf); buf += sizeof(uint32_t); size -= sizeof(uint32_t); } if (size >= sizeof(uint16_t)) { crc = _mm_crc32_u16(crc, *(uint16_t*)buf); buf += sizeof(uint16_t); size -= sizeof(uint16_t); } if (size) { crc = _mm_crc32_u8(crc, *buf); } return crc ^ 0xFFFFFFFF; } /* }}} */ #endif static inline unsigned int yac_crc32(char *data, unsigned int size) /* {{{ */ { if (size < YAC_FULL_CRC_THRESHOLD) { return yac_crc(data, size); } else { int i = 0; char crc_contents[YAC_FULL_CRC_THRESHOLD]; int head = YAC_FULL_CRC_THRESHOLD >> 2; int tail = YAC_FULL_CRC_THRESHOLD >> 4; int body = YAC_FULL_CRC_THRESHOLD - head - tail; char *p = data + head; char *q = crc_contents + head; int step = (size - tail - head) / body; memcpy(crc_contents, data, head); for (; i < body; i++, q++, p+= step) { *q = *p; } memcpy(q, p, tail); return yac_crc(crc_contents, YAC_FULL_CRC_THRESHOLD); } } /* }}} */ int yac_storage_find(const char *key, unsigned int len, char **data, unsigned int *size, unsigned int *flag, int *cas, unsigned long tv) /* {{{ */ { uint64_t h, hash, seed; yac_kv_key k, *p; yac_kv_val v; hash = h = yac_inline_hash_func1(key, len); p = &(YAC_SG(slots)[h & YAC_SG(slots_mask)]); if (!WRITEP(p)) { ++YAC_SG(miss); return 0; } k = *p; READP(p); if (k.val) { char *s; uint32_t i; if (k.h == hash && YAC_KEY_KLEN(k) == len) { v = *(k.val); if (!memcmp(k.key, key, len)) { s = USER_ALLOC(YAC_KEY_VLEN(k) + 1); memcpy(s, (char *)k.val->data, YAC_KEY_VLEN(k)); do_verify: if (k.len != v.len) { USER_FREE(s); ++YAC_SG(miss); return 0; } if (k.ttl) { if (k.ttl <= tv) { ++YAC_SG(miss); USER_FREE(s); return 0; } } if (k.crc != yac_crc32(s, YAC_KEY_VLEN(k))) { USER_FREE(s); ++YAC_SG(miss); return 0; } s[YAC_KEY_VLEN(k)] = '\0'; k.val->atime = tv; *data = s; *size = YAC_KEY_VLEN(k); *flag = k.flag; ++YAC_SG(hits); return 1; } } seed = yac_inline_hash_func2(key, len); for (i = 0; i < 3; i++) { h += seed & YAC_SG(slots_mask); p = &(YAC_SG(slots)[h & YAC_SG(slots_mask)]); if (!WRITEP(p)) { ++YAC_SG(miss); return 0; } k = *p; READP(p); if (k.h == hash && YAC_KEY_KLEN(k) == len) { v = *(k.val); if (!memcmp(k.key, key, len)) { s = USER_ALLOC(YAC_KEY_VLEN(k) + 1); memcpy(s, (char *)k.val->data, YAC_KEY_VLEN(k)); goto do_verify; } } } } ++YAC_SG(miss); return 0; } /* }}} */ int yac_storage_delete(const char *key, unsigned int len, int ttl, unsigned long tv) /* {{{ */ { uint64_t hash, h, seed; yac_kv_key k, *p; hash = h = yac_inline_hash_func1(key, len); p = &(YAC_SG(slots)[h & YAC_SG(slots_mask)]); if (!WRITEP(p)) { return 0; } k = *p; READP(p); if (k.val) { uint32_t i; if (k.h == hash && YAC_KEY_KLEN(k) == len) { if (!memcmp((char *)k.key, key, len)) { if (ttl == 0) { p->ttl = 1; } else { p->ttl = ttl + tv; } return 1; } } seed = yac_inline_hash_func2(key, len); for (i = 0; i < 3; i++) { h += seed & YAC_SG(slots_mask); p = &(YAC_SG(slots)[h & YAC_SG(slots_mask)]); if (!WRITEP(p)) { return 0; } k = *p; READP(p); if (k.val == NULL) { return 1; } else if (k.h == hash && YAC_KEY_KLEN(k) == len && !memcmp((char *)k.key, key, len)) { p->ttl = 1; return 1; } } } return 0; } /* }}} */ int yac_storage_update(const char *key, unsigned int len, char *data, unsigned int size, unsigned int flag, int ttl, int add, unsigned long tv) /* {{{ */ { uint64_t hash, h; int idx = 0, is_valid; yac_kv_key *p, k, *paths[4]; yac_kv_val *val, *s; unsigned long real_size; hash = h = yac_inline_hash_func1(key, len); paths[idx++] = p = &(YAC_SG(slots)[h & YAC_SG(slots_mask)]); if (!WRITEP(p)) { return 0; } k = *p; READP(p); if (k.val) { /* Found the exact match */ if (k.h == hash && YAC_KEY_KLEN(k) == len && !memcmp((char *)k.key, key, len)) { do_update: is_valid = 0; if (k.crc == yac_crc32(k.val->data, YAC_KEY_VLEN(k))) { is_valid = 1; } if (add && (!k.ttl || k.ttl > tv) && is_valid) { return 0; } if (k.size >= size && is_valid) { s = USER_ALLOC(sizeof(yac_kv_val) + size - 1); memcpy(s->data, data, size); if (ttl) { k.ttl = (uint64_t)tv + ttl; } else { k.ttl = 0; } s->atime = tv; YAC_KEY_SET_LEN(*s, len, size); memcpy((char *)k.val, (char *)s, sizeof(yac_kv_val) + size - 1); k.crc = yac_crc32(s->data, size); k.flag = flag; memcpy(k.key, key, len); YAC_KEY_SET_LEN(k, len, size); if (!WRITEP(p)) { USER_FREE(s); return 0; } *p = k; READP(p); USER_FREE(s); return 1; } else { uint32_t msize; real_size = yac_allocator_real_size(sizeof(yac_kv_val) + (size * YAC_STORAGE_FACTOR) - 1); if (!real_size) { ++YAC_SG(fails); return 0; } msize = sizeof(yac_kv_val) + size - 1; s = USER_ALLOC(sizeof(yac_kv_val) + size - 1); memcpy(s->data, data, size); s->atime = tv; YAC_KEY_SET_LEN(*s, len, size); val = yac_allocator_raw_alloc(real_size, (int)hash); if (val) { memcpy((char *)val, (char *)s, msize); if (ttl) { k.ttl = tv + ttl; } else { k.ttl = 0; } k.crc = yac_crc32(s->data, size); k.val = val; k.flag = flag; k.size = real_size; memcpy(k.key, key, len); YAC_KEY_SET_LEN(k, len, size); if (!WRITEP(p)) { USER_FREE(s); return 0; } *p = k; READP(p); USER_FREE(s); return 1; } ++YAC_SG(fails); USER_FREE(s); return 0; } } else { uint32_t i; uint64_t seed, max_atime; seed = yac_inline_hash_func2(key, len); for (i = 0; i < 3; i++) { h += seed & YAC_SG(slots_mask); paths[idx++] = p = &(YAC_SG(slots)[h & YAC_SG(slots_mask)]); if (!WRITEP(p)) { return 0; } k = *p; READP(p); if (k.val == NULL) { goto do_add; } else if (k.h == hash && YAC_KEY_KLEN(k) == len && !memcmp((char *)k.key, key, len)) { /* Found the exact match */ goto do_update; } } --idx; max_atime = paths[idx]->val->atime; for (i = 0; i < idx; i++) { if ((paths[i]->ttl && paths[i]->ttl <= tv) || paths[i]->len != paths[i]->val->len) { p = paths[i]; goto do_add; } else if (paths[i]->val->atime < max_atime) { max_atime = paths[i]->val->atime; p = paths[i]; } } if (!WRITEP(p)) { return 0; } k = *p; READP(p); ++YAC_SG(kicks); k.h = hash; goto do_update; } } else { do_add: real_size = yac_allocator_real_size(sizeof(yac_kv_val) + (size * YAC_STORAGE_FACTOR) - 1); if (!real_size) { ++YAC_SG(fails); return 0; } s = USER_ALLOC(sizeof(yac_kv_val) + size - 1); memcpy(s->data, data, size); s->atime = tv; YAC_KEY_SET_LEN(*s, len, size); val = yac_allocator_raw_alloc(real_size, (int)hash); if (val) { memcpy((char *)val, (char *)s, sizeof(yac_kv_val) + size - 1); if (p->val == NULL) { ++YAC_SG(slots_num); } k.h = hash; k.val = val; k.flag = flag; k.size = real_size; k.crc = yac_crc32(s->data, size); memcpy(k.key, key, len); YAC_KEY_SET_LEN(k, len, size); if (ttl) { k.ttl = tv + ttl; } else { k.ttl = 0; } if (!WRITEP(p)) { USER_FREE(s); return 0; } *p = k; READP(p); USER_FREE(s); return 1; } ++YAC_SG(fails); USER_FREE(s); } return 0; } /* }}} */ void yac_storage_flush(void) /* {{{ */ { YAC_SG(slots_num) = 0; memset((char *)YAC_SG(slots), 0, sizeof(yac_kv_key) * YAC_SG(slots_size)); } /* }}} */ yac_storage_info * yac_storage_get_info(void) /* {{{ */ { yac_storage_info *info = USER_ALLOC(sizeof(yac_storage_info)); info->k_msize = (unsigned long)YAC_SG(first_seg).size; info->v_msize = (unsigned long)YAC_SG(segments)[0]->size * (unsigned long)YAC_SG(segments_num); info->segment_size = YAC_SG(segments)[0]->size; info->segments_num = YAC_SG(segments_num); info->hits = YAC_SG(hits); info->miss = YAC_SG(miss); info->fails = YAC_SG(fails); info->kicks = YAC_SG(kicks); info->recycles = YAC_SG(recycles); info->slots_size = YAC_SG(slots_size); info->slots_num = YAC_SG(slots_num); return info; } /* }}} */ void yac_storage_free_info(yac_storage_info *info) /* {{{ */ { USER_FREE(info); } /* }}} */ yac_item_list * yac_storage_dump(unsigned int limit) /* {{{ */ { yac_kv_key k; yac_item_list *item, *list = NULL; if (YAC_SG(slots_num)) { unsigned int i = 0, n = 0; for (; iindex = i; item->h = k.h; item->crc = k.crc; item->ttl = k.ttl; item->k_len = YAC_KEY_KLEN(k); item->v_len = YAC_KEY_VLEN(k); item->flag = k.flag; item->size = k.size; memcpy(item->key, k.key, YAC_STORAGE_MAX_KEY_LEN); item->next = list; list = item; ++n; } } } return list; } /* }}} */ void yac_storage_free_list(yac_item_list *list) /* {{{ */ { yac_item_list *l; while (list) { l = list; list = list->next; USER_FREE(l); } } /* }}} */ const char * yac_storage_shared_memory_name(void) /* {{{ */ { return YAC_SHARED_MEMORY_HANDLER_NAME; } /* }}} */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ yac-2.3.1/storage/yac_atomic.h0000664000175000017500000000463514157324055017324 0ustar huixinchenhuixinchen/* +----------------------------------------------------------------------+ | Yet Another Cache | +----------------------------------------------------------------------+ | Copyright (c) 2013-2013 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: Xinchen Hui | | John Neo | +----------------------------------------------------------------------+ */ #ifndef YAC_ATOMIC_H #define YAC_ATOMIC_H #ifdef HAVE_CONFIG_H #include "config.h" #endif #if HAVE_BUILTIN_ATOMIC #define YAC_CAS(lock, old, set) __sync_bool_compare_and_swap(lock, old, set) #elif ( __amd64__ || __amd64 || __x86_64__ || __i386__ || __i386 ) static inline int __yac_cas(unsigned int *lock, unsigned int old, unsigned int set) { unsigned char res; __asm__ volatile ( "lock;" "cmpxchgl %3, %1;" "sete %0;" : "=a" (res) : "m" (*lock), "a" (old), "r" (set) : "memory"); return res; } #define YAC_CAS(lock, old, set) __yac_cas(lock, old, set) #elif ZEND_WIN32 #define YAC_CAS(lock, old, set) (InterlockedCompareExchange(lock, set, old) == old) #else #undef YAC_CAS #warning No atomic CAS supports #endif #ifdef YAC_CAS #define MUT_READ 0x0 #define MUT_WRITE 0x1 #define CAS_MAX_SPIN 100 static inline int yac_mutex_write(unsigned int *me) { int retry = 0; while (!YAC_CAS(me, MUT_READ, MUT_WRITE)) { if (++retry == CAS_MAX_SPIN) { return 0; } } return 1; } static inline void yac_mutex_read(unsigned int *me) { *me = MUT_READ; } #define WRITEP(P) yac_mutex_write(&(P->mutex)) #define READP(P) yac_mutex_read(&(P->mutex)) #else #undef YAC_CAS #define WRITEP(P) (1) #define READP(P) #endif #endif yac-2.3.1/compressor/fastlz/LICENSE0000664000175000017500000000231214157324055020071 0ustar huixinchenhuixinchenFastLZ - lightning-fast lossless compression library Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) Copyright (C) 2005 Ariya Hidayat (ariya@kde.org) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. yac-2.3.1/compressor/fastlz/README.TXT0000664000175000017500000000350714157324055020431 0ustar huixinchenhuixinchenFastLZ - lightning-fast lossless compression library Author: Ariya Hidayat Official website: http://fastlz.org FastLZ is distributed using the MIT license, see file LICENSE for details. FastLZ consists of two files: fastlz.h and fastlz.c. Just add these files to your project in order to use FastLZ. For information on compression and decompression routines, see fastlz.h. A simple file compressor called 6pack is included as an example on how to use FastLZ. The corresponding decompressor is 6unpack. To compile using GCC: gcc -o 6pack 6pack.c fastlz.c gcc -o 6unpack 6unpack.c fastlz.c To compile using MinGW: mingw32-gcc -o 6pack 6pack.c fastlz.c mingw32-gcc -o 6unpack 6unpack.c fastlz.c To compile using Microsoft Visual C++: cl 6pack.c fastlz.c cl 6unpack.c fastlz.c To compile using Borland C++: bcc32 6pack.c fastlz.c bcc32 6unpack.c fastlz.c To compile using OpenWatcom C/C++: cl386 6pack.c fastlz.c cl386 6unpack.c fastlz.c To compile using Intel C++ compiler for Windows: icl 6pack.c fastlz.c icl 6unpack.c fastlz.c To compile using Intel C++ compiler for Linux: icc -o 6pack 6pack.c fastlz.c icc -o 6unpack 6unpack.c fastlz.c To compile 6pack using LCC-Win32: lc 6pack.c fastlz.c lc 6unpack.c fastlz.c To compile 6pack using Pelles C: pocc 6pack.c pocc 6unpack.c pocc fastlz.c polink 6pack.obj fastlz.obj polink 6unpack.obj fastlz.obj For speed optimization, always use proper compile flags for optimization options. Typical compiler flags are given below: * GCC (pre 4.2): -march=pentium -O3 -fomit-frame-pointer -mtune=pentium * GCC 4.2 or later: -march=pentium -O3 -fomit-frame-pointer -mtune=generic * Digital Mars C/C++: -o+all -5 * Intel C++ (Windows): /O3 /Qipo * Intel C++ (Linux): -O2 -march=pentium -mtune=pentium * Borland C++: -O2 -5 * LCC-Win32: -O * Pelles C: /O2 yac-2.3.1/compressor/fastlz/fastlz.h0000664000175000017500000000675614157324055020560 0ustar huixinchenhuixinchen/* FastLZ - lightning-fast lossless compression library Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) Copyright (C) 2005 Ariya Hidayat (ariya@kde.org) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef FASTLZ_H #define FASTLZ_H #define FASTLZ_VERSION 0x000100 #define FASTLZ_VERSION_MAJOR 0 #define FASTLZ_VERSION_MINOR 0 #define FASTLZ_VERSION_REVISION 0 #define FASTLZ_VERSION_STRING "0.1.0" #if defined (__cplusplus) extern "C" { #endif /** Compress a block of data in the input buffer and returns the size of compressed block. The size of input buffer is specified by length. The minimum input buffer size is 16. The output buffer must be at least 5% larger than the input buffer and can not be smaller than 66 bytes. If the input is not compressible, the return value might be larger than length (input buffer size). The input buffer and the output buffer can not overlap. */ int fastlz_compress(const void* input, int length, void* output); /** Decompress a block of compressed data and returns the size of the decompressed block. If error occurs, e.g. the compressed data is corrupted or the output buffer is not large enough, then 0 (zero) will be returned instead. The input buffer and the output buffer can not overlap. Decompression is memory safe and guaranteed not to write the output buffer more than what is specified in maxout. */ int fastlz_decompress(const void* input, int length, void* output, int maxout); /** Compress a block of data in the input buffer and returns the size of compressed block. The size of input buffer is specified by length. The minimum input buffer size is 16. The output buffer must be at least 5% larger than the input buffer and can not be smaller than 66 bytes. If the input is not compressible, the return value might be larger than length (input buffer size). The input buffer and the output buffer can not overlap. Compression level can be specified in parameter level. At the moment, only level 1 and level 2 are supported. Level 1 is the fastest compression and generally useful for short data. Level 2 is slightly slower but it gives better compression ratio. Note that the compressed data, regardless of the level, can always be decompressed using the function fastlz_decompress above. */ int fastlz_compress_level(int level, const void* input, int length, void* output); #if defined (__cplusplus) } #endif #endif /* FASTLZ_H */ yac-2.3.1/compressor/fastlz/fastlz.c0000664000175000017500000003252014157324055020537 0ustar huixinchenhuixinchen/* FastLZ - lightning-fast lossless compression library Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) Copyright (C) 2005 Ariya Hidayat (ariya@kde.org) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if !defined(FASTLZ__COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) /* * Always check for bound when decompressing. * Generally it is best to leave it defined. */ #define FASTLZ_SAFE /* * Give hints to the compiler for branch prediction optimization. */ #if defined(__GNUC__) && (__GNUC__ > 2) #define FASTLZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1)) #define FASTLZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0)) #else #define FASTLZ_EXPECT_CONDITIONAL(c) (c) #define FASTLZ_UNEXPECT_CONDITIONAL(c) (c) #endif /* * Use inlined functions for supported systems. */ #if defined(__GNUC__) || defined(__DMC__) || defined(__POCC__) || defined(__WATCOMC__) || defined(__SUNPRO_C) #define FASTLZ_INLINE inline #elif defined(__BORLANDC__) || defined(_MSC_VER) || defined(__LCC__) #define FASTLZ_INLINE __inline #else #define FASTLZ_INLINE #endif /* * Prevent accessing more than 8-bit at once, except on x86 architectures. */ #if !defined(FASTLZ_STRICT_ALIGN) #define FASTLZ_STRICT_ALIGN #if defined(__i386__) || defined(__386) /* GNU C, Sun Studio */ #undef FASTLZ_STRICT_ALIGN #elif defined(__i486__) || defined(__i586__) || defined(__i686__) /* GNU C */ #undef FASTLZ_STRICT_ALIGN #elif defined(_M_IX86) /* Intel, MSVC */ #undef FASTLZ_STRICT_ALIGN #elif defined(__386) #undef FASTLZ_STRICT_ALIGN #elif defined(_X86_) /* MinGW */ #undef FASTLZ_STRICT_ALIGN #elif defined(__I86__) /* Digital Mars */ #undef FASTLZ_STRICT_ALIGN #endif #endif /* * FIXME: use preprocessor magic to set this on different platforms! */ typedef unsigned char flzuint8; typedef unsigned short flzuint16; typedef unsigned int flzuint32; /* prototypes */ int fastlz_compress(const void* input, int length, void* output); int fastlz_compress_level(int level, const void* input, int length, void* output); int fastlz_decompress(const void* input, int length, void* output, int maxout); #define MAX_COPY 32 #define MAX_LEN 264 /* 256 + 8 */ #define MAX_DISTANCE 8192 #if !defined(FASTLZ_STRICT_ALIGN) #define FASTLZ_READU16(p) *((const flzuint16*)(p)) #else #define FASTLZ_READU16(p) ((p)[0] | (p)[1]<<8) #endif #define HASH_LOG 13 #define HASH_SIZE (1<< HASH_LOG) #define HASH_MASK (HASH_SIZE-1) #define HASH_FUNCTION(v,p) { v = FASTLZ_READU16(p); v ^= FASTLZ_READU16(p+1)^(v>>(16-HASH_LOG));v &= HASH_MASK; } #undef FASTLZ_LEVEL #define FASTLZ_LEVEL 1 #undef FASTLZ_COMPRESSOR #undef FASTLZ_DECOMPRESSOR #define FASTLZ_COMPRESSOR fastlz1_compress #define FASTLZ_DECOMPRESSOR fastlz1_decompress static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output); static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout); #include "fastlz.c" #undef FASTLZ_LEVEL #define FASTLZ_LEVEL 2 #undef MAX_DISTANCE #define MAX_DISTANCE 8191 #define MAX_FARDISTANCE (65535+MAX_DISTANCE-1) #undef FASTLZ_COMPRESSOR #undef FASTLZ_DECOMPRESSOR #define FASTLZ_COMPRESSOR fastlz2_compress #define FASTLZ_DECOMPRESSOR fastlz2_decompress static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output); static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout); #include "fastlz.c" int fastlz_compress(const void* input, int length, void* output) { /* for short block, choose fastlz1 */ if(length < 65536) return fastlz1_compress(input, length, output); /* else... */ return fastlz2_compress(input, length, output); } int fastlz_decompress(const void* input, int length, void* output, int maxout) { /* magic identifier for compression level */ int level = ((*(const flzuint8*)input) >> 5) + 1; if(level == 1) return fastlz1_decompress(input, length, output, maxout); if(level == 2) return fastlz2_decompress(input, length, output, maxout); /* unknown level, trigger error */ return 0; } int fastlz_compress_level(int level, const void* input, int length, void* output) { if(level == 1) return fastlz1_compress(input, length, output); if(level == 2) return fastlz2_compress(input, length, output); return 0; } #else /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */ static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output) { const flzuint8* ip = (const flzuint8*) input; const flzuint8* ip_bound = ip + length - 2; const flzuint8* ip_limit = ip + length - 12; flzuint8* op = (flzuint8*) output; const flzuint8* htab[HASH_SIZE]; const flzuint8** hslot; flzuint32 hval; flzuint32 copy; /* sanity check */ if(FASTLZ_UNEXPECT_CONDITIONAL(length < 4)) { if(length) { /* create literal copy only */ *op++ = length-1; ip_bound++; while(ip <= ip_bound) *op++ = *ip++; return length+1; } else return 0; } /* initializes hash table */ for (hslot = htab; hslot < htab + HASH_SIZE; hslot++) *hslot = ip; /* we start with literal copy */ copy = 2; *op++ = MAX_COPY-1; *op++ = *ip++; *op++ = *ip++; /* main loop */ while(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit)) { const flzuint8* ref; flzuint32 distance; /* minimum match length */ flzuint32 len = 3; /* comparison starting-point */ const flzuint8* anchor = ip; /* check for a run */ #if FASTLZ_LEVEL==2 if(ip[0] == ip[-1] && FASTLZ_READU16(ip-1)==FASTLZ_READU16(ip+1)) { distance = 1; ip += 3; ref = anchor - 1 + 3; goto match; } #endif /* find potential match */ HASH_FUNCTION(hval,ip); hslot = htab + hval; ref = htab[hval]; /* calculate distance to the match */ distance = anchor - ref; /* update hash table */ *hslot = anchor; /* is this a match? check the first 3 bytes */ if(distance==0 || #if FASTLZ_LEVEL==1 (distance >= MAX_DISTANCE) || #else (distance >= MAX_FARDISTANCE) || #endif *ref++ != *ip++ || *ref++!=*ip++ || *ref++!=*ip++) goto literal; #if FASTLZ_LEVEL==2 /* far, needs at least 5-byte match */ if(distance >= MAX_DISTANCE) { if(*ip++ != *ref++ || *ip++!= *ref++) goto literal; len += 2; } match: #endif /* last matched byte */ ip = anchor + len; /* distance is biased */ distance--; if(!distance) { /* zero distance means a run */ flzuint8 x = ip[-1]; while(ip < ip_bound) if(*ref++ != x) break; else ip++; } else for(;;) { /* safe because the outer check against ip limit */ if(*ref++ != *ip++) break; if(*ref++ != *ip++) break; if(*ref++ != *ip++) break; if(*ref++ != *ip++) break; if(*ref++ != *ip++) break; if(*ref++ != *ip++) break; if(*ref++ != *ip++) break; if(*ref++ != *ip++) break; while(ip < ip_bound) if(*ref++ != *ip++) break; break; } /* if we have copied something, adjust the copy count */ if(copy) /* copy is biased, '0' means 1 byte copy */ *(op-copy-1) = copy-1; else /* back, to overwrite the copy count */ op--; /* reset literal counter */ copy = 0; /* length is biased, '1' means a match of 3 bytes */ ip -= 3; len = ip - anchor; /* encode the match */ #if FASTLZ_LEVEL==2 if(distance < MAX_DISTANCE) { if(len < 7) { *op++ = (len << 5) + (distance >> 8); *op++ = (distance & 255); } else { *op++ = (7 << 5) + (distance >> 8); for(len-=7; len >= 255; len-= 255) *op++ = 255; *op++ = len; *op++ = (distance & 255); } } else { /* far away, but not yet in the another galaxy... */ if(len < 7) { distance -= MAX_DISTANCE; *op++ = (len << 5) + 31; *op++ = 255; *op++ = distance >> 8; *op++ = distance & 255; } else { distance -= MAX_DISTANCE; *op++ = (7 << 5) + 31; for(len-=7; len >= 255; len-= 255) *op++ = 255; *op++ = len; *op++ = 255; *op++ = distance >> 8; *op++ = distance & 255; } } #else if(FASTLZ_UNEXPECT_CONDITIONAL(len > MAX_LEN-2)) while(len > MAX_LEN-2) { *op++ = (7 << 5) + (distance >> 8); *op++ = MAX_LEN - 2 - 7 -2; *op++ = (distance & 255); len -= MAX_LEN-2; } if(len < 7) { *op++ = (len << 5) + (distance >> 8); *op++ = (distance & 255); } else { *op++ = (7 << 5) + (distance >> 8); *op++ = len - 7; *op++ = (distance & 255); } #endif /* update the hash at match boundary */ HASH_FUNCTION(hval,ip); htab[hval] = ip++; HASH_FUNCTION(hval,ip); htab[hval] = ip++; /* assuming literal copy */ *op++ = MAX_COPY-1; continue; literal: *op++ = *anchor++; ip = anchor; copy++; if(FASTLZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY)) { copy = 0; *op++ = MAX_COPY-1; } } /* left-over as literal copy */ ip_bound++; while(ip <= ip_bound) { *op++ = *ip++; copy++; if(copy == MAX_COPY) { copy = 0; *op++ = MAX_COPY-1; } } /* if we have copied something, adjust the copy length */ if(copy) *(op-copy-1) = copy-1; else op--; #if FASTLZ_LEVEL==2 /* marker for fastlz2 */ *(flzuint8*)output |= (1 << 5); #endif return op - (flzuint8*)output; } static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void* output, int maxout) { const flzuint8* ip = (const flzuint8*) input; const flzuint8* ip_limit = ip + length; flzuint8* op = (flzuint8*) output; flzuint8* op_limit = op + maxout; flzuint32 ctrl = (*ip++) & 31; int loop = 1; do { const flzuint8* ref = op; flzuint32 len = ctrl >> 5; flzuint32 ofs = (ctrl & 31) << 8; if(ctrl >= 32) { #if FASTLZ_LEVEL==2 flzuint8 code; #endif len--; ref -= ofs; if (len == 7-1) #if FASTLZ_LEVEL==1 len += *ip++; ref -= *ip++; #else do { code = *ip++; len += code; } while (code==255); code = *ip++; ref -= code; /* match from 16-bit distance */ if(FASTLZ_UNEXPECT_CONDITIONAL(code==255)) if(FASTLZ_EXPECT_CONDITIONAL(ofs==(31 << 8))) { ofs = (*ip++) << 8; ofs += *ip++; ref = op - ofs - MAX_DISTANCE; } #endif #ifdef FASTLZ_SAFE if (FASTLZ_UNEXPECT_CONDITIONAL(op + len + 3 > op_limit)) return 0; if (FASTLZ_UNEXPECT_CONDITIONAL(ref-1 < (flzuint8 *)output)) return 0; #endif if(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit)) ctrl = *ip++; else loop = 0; if(ref == op) { /* optimize copy for a run */ flzuint8 b = ref[-1]; *op++ = b; *op++ = b; *op++ = b; for(; len; --len) *op++ = b; } else { #if !defined(FASTLZ_STRICT_ALIGN) const flzuint16* p; flzuint16* q; #endif /* copy from reference */ ref--; *op++ = *ref++; *op++ = *ref++; *op++ = *ref++; #if !defined(FASTLZ_STRICT_ALIGN) /* copy a byte, so that now it's word aligned */ if(len & 1) { *op++ = *ref++; len--; } /* copy 16-bit at once */ q = (flzuint16*) op; op += len; p = (const flzuint16*) ref; for(len>>=1; len > 4; len-=4) { *q++ = *p++; *q++ = *p++; *q++ = *p++; *q++ = *p++; } for(; len; --len) *q++ = *p++; #else for(; len; --len) *op++ = *ref++; #endif } } else { ctrl++; #ifdef FASTLZ_SAFE if (FASTLZ_UNEXPECT_CONDITIONAL(op + ctrl > op_limit)) return 0; if (FASTLZ_UNEXPECT_CONDITIONAL(ip + ctrl > ip_limit)) return 0; #endif *op++ = *ip++; for(--ctrl; ctrl; ctrl--) *op++ = *ip++; loop = FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit); if(loop) ctrl = *ip++; } } while(FASTLZ_EXPECT_CONDITIONAL(loop)); return op - (flzuint8*)output; } #endif /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */ yac-2.3.1/serializer/yac_serializer.h0000664000175000017500000000426014157324055020720 0ustar huixinchenhuixinchen/* +----------------------------------------------------------------------+ | Yet Another Cache | +----------------------------------------------------------------------+ | Copyright (c) 2013-2013 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: Xinchen Hui | +----------------------------------------------------------------------+ */ /* $Id$ */ #ifndef YAC_SERIALIZER_H #define YAC_SERIALIZER_H typedef int (*yac_serializer_t)(zval*, smart_str*, char**); typedef zval* (*yac_unserializer_t)(char *, size_t, char**, zval*); #ifdef YAC_ENABLE_MSGPACK int yac_serializer_msgpack_pack(zval *pzval, smart_str *buf, char **msg); zval * yac_serializer_msgpack_unpack(char *content, size_t len, char **msg, zval *rv); #endif int yac_serializer_php_pack(zval *pzval, smart_str *buf, char **msg); zval * yac_serializer_php_unpack(char *content, size_t len, char **msg, zval *rv); #ifdef YAC_ENABLE_IGBINARY int yac_serializer_igbinary_pack(zval *pzval, smart_str *buf, char **msg); zval * yac_serializer_igbinary_unpack(char *content, size_t len, char **msg, zval *rv); #endif #ifdef YAC_ENABLE_JSON int yac_serializer_json_pack(zval *pzval, smart_str *buf, char **msg); zval * yac_serializer_json_unpack(char *content, size_t len, char **msg, zval *rv); #endif #endif /* YAC_SERIALIZER_H */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ yac-2.3.1/serializer/php.c0000664000175000017500000000432714157324055016501 0ustar huixinchenhuixinchen/* +----------------------------------------------------------------------+ | Yet Another Cache | +----------------------------------------------------------------------+ | Copyright (c) 2013-2013 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: Xinchen Hui | +----------------------------------------------------------------------+ */ /* $Id$ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "php.h" #include "ext/standard/php_var.h" /* for serialize */ #include "zend_smart_str.h" #include "yac_serializer.h" int yac_serializer_php_pack(zval *pzval, smart_str *buf, char **msg) /* {{{ */ { php_serialize_data_t var_hash; PHP_VAR_SERIALIZE_INIT(var_hash); php_var_serialize(buf, pzval, &var_hash); PHP_VAR_SERIALIZE_DESTROY(var_hash); return 1; } /* }}} */ zval * yac_serializer_php_unpack(char *content, size_t len, char **msg, zval *rv) /* {{{ */ { const unsigned char *p; php_unserialize_data_t var_hash; p = (const unsigned char*)content; ZVAL_FALSE(rv); PHP_VAR_UNSERIALIZE_INIT(var_hash); if (!php_var_unserialize(rv, &p, p + len, &var_hash)) { zval_ptr_dtor(rv); PHP_VAR_UNSERIALIZE_DESTROY(var_hash); /* spprintf(msg, 0, "unpack error at offset %ld of %ld bytes", (long)((char*)p - content), len); */ return NULL; } PHP_VAR_UNSERIALIZE_DESTROY(var_hash); return rv; } /* }}} */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ yac-2.3.1/serializer/msgpack.c0000664000175000017500000000355314157324055017337 0ustar huixinchenhuixinchen/* +----------------------------------------------------------------------+ | Yar - Light, concurrent RPC framework | +----------------------------------------------------------------------+ | Copyright (c) 2012-2013 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: Xinchen Hui | | Zhenyu Zhang | +----------------------------------------------------------------------+ */ /* $Id$ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef YAC_ENABLE_MSGPACK #include "php.h" #include "ext/msgpack/php_msgpack.h" #include "zend_smart_str.h" /* for smart_str */ #include "yac_serializer.h" int yac_serializer_msgpack_pack(zval *pzval, smart_str *buf, char **msg) /* {{{ */ { php_msgpack_serialize(buf, pzval); return 1; } /* }}} */ zval * yac_serializer_msgpack_unpack(char *content, size_t len, char **msg, zval *rv) /* {{{ */ { ZVAL_NULL(rv); php_msgpack_unserialize(rv, content, len); return rv; } /* }}} */ #endif /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ yac-2.3.1/serializer/json.c0000664000175000017500000000357714157324055016671 0ustar huixinchenhuixinchen/* +----------------------------------------------------------------------+ | Yet Another Cache | +----------------------------------------------------------------------+ | Copyright (c) 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: Xinchen Hui | +----------------------------------------------------------------------+ */ /* $Id$ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #if YAC_ENABLE_JSON #include "php.h" #include "ext/json/php_json.h" #include "zend_smart_str.h" /* for smart_str */ #include "yac_serializer.h" int yac_serializer_json_pack(zval *pzval, smart_str *buf, char **msg) /* {{{ */ { #if ((PHP_MAJOR_VERSION == 5) && (PHP_MINOR_VERSION < 3)) php_json_encode(buf, pzval); #else php_json_encode(buf, pzval, 0); /* options */ #endif return 1; } /* }}} */ zval* yac_serializer_json_unpack(char *content, size_t len, char **msg, zval *rv) /* {{{ */ { ZVAL_NULL(rv); php_json_decode(rv, content, len, 1, 512); return rv; } /* }}} */ #endif /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ yac-2.3.1/serializer/igbinary.c0000664000175000017500000000376014157324055017516 0ustar huixinchenhuixinchen/* +----------------------------------------------------------------------+ | Yet Another Cache | +----------------------------------------------------------------------+ | Copyright (c) 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: Xinchen Hui | | Remi Collet | +----------------------------------------------------------------------+ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef YAC_ENABLE_IGBINARY #include "php.h" #include "ext/igbinary/igbinary.h" #include "zend_smart_str.h" /* for smart_str */ #include "yac_serializer.h" int yac_serializer_igbinary_pack(zval *pzval, smart_str *buf, char **msg) /* {{{ */ { uint8_t *ret; size_t ret_len; if (igbinary_serialize(&ret, &ret_len, pzval) == 0) { smart_str_appendl(buf, (const char *)ret, ret_len); efree(ret); return 1; } return 0; } /* }}} */ zval * yac_serializer_igbinary_unpack(char *content, size_t len, char **msg, zval *rv) /* {{{ */ { ZVAL_NULL(rv); igbinary_unserialize((uint8_t *)content, len, rv); return rv; } /* }}} */ #endif /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ yac-2.3.1/tests/001.phpt0000664000175000017500000000102114157324055015720 0ustar huixinchenhuixinchen--TEST-- Check for yac presence --SKIPIF-- --FILE-- --EXPECT-- yac extension is available yac-2.3.1/tests/002.phpt0000664000175000017500000000310414157324055015725 0ustar huixinchenhuixinchen--TEST-- Check for yac basic functions --SKIPIF-- --INI-- yac.enable=1 yac.enable_cli=1 yac.keys_memory_size=4M yac.values_memory_size=32M yac.serializer=php --FILE-- set($key, $value)); var_dump($yac->get($key)); $value = NULL; var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = TRUE; var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = FALSE; var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = range(1, 5); var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = 9234324; var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = 9234324.123456; var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = new StdClass();; var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = fopen("php://input", "r"); var_dump($yac->set($key, $value)); $value = range(1, 5); var_dump($yac->set($key, $value)); var_dump($yac->delete($key)); var_dump($yac->get($key)); ?> --EXPECTF-- bool(true) bool(true) string(5) "dummy" bool(true) NULL bool(true) bool(true) bool(true) bool(false) bool(true) array(5) { [0]=> int(1) [1]=> int(2) [2]=> int(3) [3]=> int(4) [4]=> int(5) } bool(true) int(9234324) bool(true) float(9234324.123456) bool(true) object(stdClass)#3 (0) { } Warning: Yac::set(): Type 'IS_RESOURCE' cannot be stored in %s002.php on line %d bool(false) bool(true) bool(true) bool(false) yac-2.3.1/tests/003.phpt0000664000175000017500000000240714157324055015733 0ustar huixinchenhuixinchen--TEST-- Check for yac errors --SKIPIF-- --INI-- yac.enable=1 yac.enable_cli=1 yac.keys_memory_size=4M yac.values_memory_size=32M --FILE-- set($key, $value)); var_dump($yac->get($key)); $key = str_repeat("k", YAC_MAX_KEY_LEN); var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $key = str_repeat("k", YAC_MAX_KEY_LEN + 1); var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $yac = new Yac("dummy"); var_dump($yac->set($key, $value)); var_dump($yac->get($key)); ?> --EXPECTF-- bool(true) NULL bool(true) NULL Warning: Yac::set(): Key 'kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk' exceed max key length '48' bytes in %s003.php on line %d bool(false) Warning: Yac::get(): Key 'kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk' exceed max key length '48' bytes in %s003.php on line %d bool(false) Warning: Yac::set(): Key 'dummykkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk' exceed max key length '48' bytes in %s003.php on line %d bool(false) Warning: Yac::get(): Key 'dummykkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk' exceed max key length '48' bytes in %s003.php on line %d bool(false) yac-2.3.1/tests/004.phpt0000664000175000017500000000117514157324055015735 0ustar huixinchenhuixinchen--TEST-- Check for yac ttl --SKIPIF-- --INI-- yac.enable=1 yac.enable_cli=1 yac.keys_memory_size=4M yac.values_memory_size=32M --FILE-- set($key, $value, 1)); var_dump($yac->get($key)); sleep(1); var_dump($yac->get($key)); var_dump($yac->set($key, $value)); var_dump($yac->get($key)); var_dump($yac->delete($key, 1)); var_dump($yac->get($key)); sleep(1); var_dump($yac->get($key)); ?> --EXPECTF-- bool(true) string(5) "dummy" bool(false) bool(true) string(5) "dummy" bool(true) string(5) "dummy" bool(false) yac-2.3.1/tests/005.phpt0000664000175000017500000000145314157324055015735 0ustar huixinchenhuixinchen--TEST-- Check for yac non-string key --SKIPIF-- --INI-- yac.enable=1 yac.enable_cli=1 yac.keys_memory_size=4M yac.values_memory_size=32M --FILE-- set($key, $value, 1)); var_dump($yac->get($key)); $key = 12345.12345; var_dump($yac->set($key, $value, 1)); var_dump($yac->get($key)); $key = range(1, 2); var_dump($yac->set($key, $value, 1)); var_dump($yac->get($key)); $key = new StdClass(); var_dump($yac->set($key, $value, 1)); var_dump($yac->get($key)); ?> --EXPECTF-- bool(true) string(5) "dummy" bool(true) string(5) "dummy" bool(true) array(2) { [1]=> int(2) [2]=> bool(false) } %s error:%sObject of class stdClass could not be converted to string in %s005.php%A yac-2.3.1/tests/006.phpt0000664000175000017500000000112314157324055015730 0ustar huixinchenhuixinchen--TEST-- Check for yac multi set/get --SKIPIF-- --INI-- yac.enable=1 yac.enable_cli=1 yac.keys_memory_size=4M yac.values_memory_size=32M --FILE-- set($key, $value)) { var_dump($key, $value); var_dump("write " . $i); } if ($value != ($new = $yac->get($key))) { var_dump($new); var_dump("read " . $i); } } var_dump($i); --EXPECTF-- int(1000) yac-2.3.1/tests/007.phpt0000664000175000017500000000137514157324055015742 0ustar huixinchenhuixinchen--TEST-- Check for yac info --SKIPIF-- --INI-- yac.enable=1 yac.enable_cli=1 yac.keys_memory_size=4M yac.values_memory_size=32M --FILE-- set($key, $value)) { var_dump($key, $value); var_dump("write " . $i); } if ($value != ($new = $yac->get($key))) { var_dump($new); var_dump("read " . $i); } } $info = $yac->info(); var_dump($info['slots_used'] <= 1000); var_dump($info['hits']); var_dump($info['miss']); var_dump($info['fails']); var_dump($info['kicks']); --EXPECTF-- bool(true) int(1000) int(0) int(0) int(0) yac-2.3.1/tests/008.phpt0000664000175000017500000000133314157324055015735 0ustar huixinchenhuixinchen--TEST-- Check for yac prefix --SKIPIF-- --INI-- yac.enable=1 yac.enable_cli=1 yac.keys_memory_size=4M yac.values_memory_size=32M --FILE-- set($key, $value); var_dump($yac->get($key)); //true var_dump($yac2->get($key)); //false var_dump($yac2->get("dummy_" . $key)); //true $yac2->delete($key); //fail var_dump($yac->get($key)); //true $yac->delete($key); //okey var_dump($yac->get($key)); //false $yac->set($key, $value); $yac2->delete("dummy_" . $key); //okey var_dump($yac->get($key)); //false ?> --EXPECTF-- bool(true) bool(false) bool(true) bool(true) bool(false) bool(false) yac-2.3.1/tests/009.phpt0000664000175000017500000000143014157324055015734 0ustar huixinchenhuixinchen--TEST-- Check for yac multi ops --SKIPIF-- --INI-- yac.enable=1 yac.enable_cli=1 yac.keys_memory_size=4M yac.values_memory_size=32M --FILE-- set($values)); $keys = array_keys($values); $ret = $yac->get($keys); var_dump(count(array_filter($ret)) == $numbers); $disable = array_slice($keys, 0, -10); $yac->delete($disable); $ret = $yac->get($keys); var_dump(count(array_filter($ret)) == 10); ?> --EXPECTF-- bool(true) bool(true) bool(true) yac-2.3.1/tests/010.phpt0000664000175000017500000000120614157324055015725 0ustar huixinchenhuixinchen--TEST-- Check for yac::flush --SKIPIF-- --INI-- yac.enable=1 yac.enable_cli=1 yac.keys_memory_size=4M yac.values_memory_size=32M --FILE-- set($values)); $yac->flush(); var_dump($yac->get($key)); $info = $yac->info(); var_dump($info['slots_used']); ?> --EXPECTF-- bool(true) bool(false) int(0) yac-2.3.1/tests/011.phpt0000664000175000017500000000143014157324055015725 0ustar huixinchenhuixinchen--TEST-- Check for yac::add --SKIPIF-- --INI-- yac.enable=1 yac.enable_cli=1 yac.keys_memory_size=4M yac.values_memory_size=32M --FILE-- add($key, $value)); // true var_dump($yac->add($key, $value)); // false var_dump($yac->set($key, $value)); // true var_dump($yac->get($key)); // foo var_dump($yac->delete($key)); // true $value = "bar"; var_dump($yac->add($key, $value, 1)); //true var_dump($yac->add($key, $value, 1)); //false var_dump($yac->get($key)); //bar sleep(1); var_dump($yac->add($key, $value)); //true ?> --EXPECTF-- bool(true) bool(false) bool(true) string(3) "foo" bool(true) bool(true) bool(false) string(3) "bar" bool(true) yac-2.3.1/tests/012.phpt0000664000175000017500000000126614157324055015735 0ustar huixinchenhuixinchen--TEST-- Check for functional apis --SKIPIF-- --INI-- yac.enable=1 yac.enable_cli=1 yac.keys_memory_size=4M yac.values_memory_size=32M --FILE-- --EXPECTF-- bool(true) bool(false) string(3) "foo" bool(true) bool(true) bool(true) int(0) yac-2.3.1/tests/013.phpt0000664000175000017500000000046514157324055015736 0ustar huixinchenhuixinchen--TEST-- Check for ttl bug --SKIPIF-- --INI-- yac.enable=1 yac.enable_cli=1 yac.keys_memory_size=4M yac.values_memory_size=32M --FILE-- set('test', 1, 1); sleep(2); var_dump($yac->get('test')); ?> --EXPECTF-- bool(false) yac-2.3.1/tests/014.phpt0000664000175000017500000000064714157324055015741 0ustar huixinchenhuixinchen--TEST-- Check for ttl bug --SKIPIF-- --INI-- yac.enable=1 yac.enable_cli=1 yac.keys_memory_size=4M yac.values_memory_size=32M yac.compress_threshold=1024 --FILE-- set('test', $value); echo count($yac->get('test')); ?> --EXPECTF-- 100 yac-2.3.1/tests/015.phpt0000664000175000017500000000067714157324055015745 0ustar huixinchenhuixinchen--TEST-- Check for Yac::dump --SKIPIF-- --INI-- yac.enable=1 yac.enable_cli=1 yac.keys_memory_size=4M yac.values_memory_size=32M yac.compress_threshold=1024 --FILE-- set("key". $i, "kjslkdfkldasjkf"); } for ($i = 0; $i<100; $i++) { $yac->set("key". $i, "kjslkdfkldasjkf"); } var_dump(count($yac->dump(1000))); --EXPECTF-- int(100) yac-2.3.1/tests/016.phpt0000664000175000017500000000057614157324055015744 0ustar huixinchenhuixinchen--TEST-- Check for Yac setter/getter --SKIPIF-- --INI-- yac.enable=1 yac.enable_cli=1 yac.keys_memory_size=4M yac.values_memory_size=32M yac.compress_threshold=1024 --FILE-- name = "test"; var_dump($yac->name); var_dump($yac->get("name")); ?> --EXPECTF-- string(4) "test" string(4) "test" yac-2.3.1/tests/017.phpt0000664000175000017500000000152414157324055015737 0ustar huixinchenhuixinchen--TEST-- Check for mutiple process --SKIPIF-- --INI-- yac.enable=1 yac.enable_cli=1 yac.keys_memory_size=4M yac.values_memory_size=32M yac.compress_threshold=1024 --FILE-- set("parent", "FIN")); while (!($msg = $yac->get("child"))); echo "MSG From Child:", $msg,"\n"; while(!($yac->set("parent", "BYE"))); pcntl_wait($status); echo "Parent exiting\n"; } else { while(!($msg = $yac->get("parent"))); echo "MSG From Parent:" , $msg, "\n"; while(!($yac->set("child", "ACK"))); while(($msg = $yac->get("parent")) != "BYE"); echo "Child exiting\n"; } ?> --EXPECT-- MSG From Parent:FIN MSG From Child:ACK Child exiting Parent exiting yac-2.3.1/tests/018.phpt0000664000175000017500000000321314157324055015735 0ustar huixinchenhuixinchen--TEST-- Check for yac with json serializer --SKIPIF-- --INI-- yac.enable=1 yac.enable_cli=1 yac.keys_memory_size=4M yac.values_memory_size=32M yac.serializer=json --FILE-- set($key, $value)); var_dump($yac->get($key)); $value = NULL; var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = TRUE; var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = FALSE; var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = range(1, 5); var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = 9234324; var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = 9234324.123456; var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = new StdClass();; var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = fopen("php://input", "r"); var_dump($yac->set($key, $value)); $value = range(1, 5); var_dump($yac->set($key, $value)); var_dump($yac->delete($key)); var_dump($yac->get($key)); ?> --EXPECTF-- bool(true) bool(true) string(5) "dummy" bool(true) NULL bool(true) bool(true) bool(true) bool(false) bool(true) array(5) { [0]=> int(1) [1]=> int(2) [2]=> int(3) [3]=> int(4) [4]=> int(5) } bool(true) int(9234324) bool(true) float(9234324.123456) bool(true) array(0) { } Warning: Yac::set(): Type 'IS_RESOURCE' cannot be stored in %s018.php on line %d bool(false) bool(true) bool(true) bool(false) yac-2.3.1/tests/019.phpt0000664000175000017500000000325114157324055015740 0ustar huixinchenhuixinchen--TEST-- Check for yac with msgpack serializer --SKIPIF-- --INI-- yac.enable=1 yac.enable_cli=1 yac.keys_memory_size=4M yac.values_memory_size=32M yac.serializer=msgpack --FILE-- set($key, $value)); var_dump($yac->get($key)); $value = NULL; var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = TRUE; var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = FALSE; var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = range(1, 5); var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = 9234324; var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = 9234324.123456; var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = new StdClass();; var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = fopen("php://input", "r"); var_dump($yac->set($key, $value)); $value = range(1, 5); var_dump($yac->set($key, $value)); var_dump($yac->delete($key)); var_dump($yac->get($key)); ?> --EXPECTF-- bool(true) bool(true) string(5) "dummy" bool(true) NULL bool(true) bool(true) bool(true) bool(false) bool(true) array(5) { [0]=> int(1) [1]=> int(2) [2]=> int(3) [3]=> int(4) [4]=> int(5) } bool(true) int(9234324) bool(true) float(9234324.123456) bool(true) object(stdClass)#%d (0) { } Warning: Yac::set(): Type 'IS_RESOURCE' cannot be stored in %s019.php on line %d bool(false) bool(true) bool(true) bool(false) yac-2.3.1/tests/020.phpt0000664000175000017500000000325614157324055015735 0ustar huixinchenhuixinchen--TEST-- Check for yac with igbinary serializer --SKIPIF-- --INI-- yac.enable=1 yac.enable_cli=1 yac.keys_memory_size=4M yac.values_memory_size=32M yac.serializer=igbinary --FILE-- set($key, $value)); var_dump($yac->get($key)); $value = NULL; var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = TRUE; var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = FALSE; var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = range(1, 5); var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = 9234324; var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = 9234324.123456; var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = new StdClass();; var_dump($yac->set($key, $value)); var_dump($yac->get($key)); $value = fopen("php://input", "r"); var_dump($yac->set($key, $value)); $value = range(1, 5); var_dump($yac->set($key, $value)); var_dump($yac->delete($key)); var_dump($yac->get($key)); ?> --EXPECTF-- bool(true) bool(true) string(5) "dummy" bool(true) NULL bool(true) bool(true) bool(true) bool(false) bool(true) array(5) { [0]=> int(1) [1]=> int(2) [2]=> int(3) [3]=> int(4) [4]=> int(5) } bool(true) int(9234324) bool(true) float(9234324.123456) bool(true) object(stdClass)#%d (0) { } Warning: Yac::set(): Type 'IS_RESOURCE' cannot be stored in %s020.php on line %d bool(false) bool(true) bool(true) bool(false) yac-2.3.1/tests/021.phpt0000664000175000017500000000116114157324055015727 0ustar huixinchenhuixinchen--TEST-- Check for yac read/write/unset property --SKIPIF-- --INI-- yac.enable=1 yac.enable_cli=1 yac.keys_memory_size=4M yac.values_memory_size=32M --FILE-- value = "value"; /* can not used in writen context */ try { $yac->foo->bar = "bar"; } catch (Exception $e) {}; var_dump($yac->get("value")); var_dump($yac->value); var_dump($yac->get("foo")); var_dump($yac->foo); unset($yac->value); var_dump($yac->get("value")); var_dump($yac->value); ?> --EXPECT-- string(5) "value" string(5) "value" bool(false) NULL bool(false) NULL yac-2.3.1/tests/022.phpt0000664000175000017500000000047214157324055015734 0ustar huixinchenhuixinchen--TEST-- Check for yac::__construct with yac.enable=0 --SKIPIF-- --INI-- yac.enable=0 --FILE-- getMessage()); } @var_dump($yac); ?> --EXPECTF-- string(18) "Yac is not enabled" NULL yac-2.3.1/tests/023.phpt0000664000175000017500000000033114157324055015727 0ustar huixinchenhuixinchen--TEST-- Check for inherit from Yac --SKIPIF-- --INI-- yac.enable=0 --FILE-- --EXPECTF-- Fatal error: Class Sub %s final class %s yac-2.3.1/tests/issue012.phpt0000664000175000017500000000057014157324055017003 0ustar huixinchenhuixinchen--TEST-- ISSUE #12 segfault if use mmap&k_size bigger than 4M --SKIPIF-- --INI-- yac.enable=1 yac.enable_cli=1 yac.keys_memory_size=8M yac.values_memory_size=128M --FILE-- set(rand(), strval(rand()), 2); $i++; if ($i > 20000) { break; } } ?> OKEY --EXPECTF-- OKEY yac-2.3.1/config.w320000664000175000017500000000233514157324055015174 0ustar huixinchenhuixinchen// $Id$ // vim:ft=javascript ARG_ENABLE("yac", "enable yac support", "no"); if (PHP_YAC != "no") { if( CHECK_HEADER_ADD_INCLUDE("fastlz.h", "CFLAGS_YAC", PHP_YAC + ";" + configure_module_dirname + "\\compressor\\fastlz") && CHECK_HEADER_ADD_INCLUDE("yac_serializer.h", "CFLAGS_YAC", PHP_YAC + ";" + configure_module_dirname + "\\serializer") && CHECK_HEADER_ADD_INCLUDE("yac_storage.h", "CFLAGS_YAC", PHP_YAC + ";" + configure_module_dirname + "\\storage") && CHECK_HEADER_ADD_INCLUDE("yac_allocator.h", "CFLAGS_YAC", PHP_YAC + ";" + configure_module_dirname + "\\storage\\allocator")) { EXTENSION("yac", "yac.c"); ADD_SOURCES(configure_module_dirname + "\\compressor\\fastlz", "fastlz.c", "yac"); ADD_SOURCES(configure_module_dirname + "\\serializer", "php.c", "yac"); ADD_SOURCES(configure_module_dirname + "\\storage", "yac_storage.c", "yac"); ADD_SOURCES(configure_module_dirname + "\\storage\\allocator", "yac_allocator.c", "yac"); ADD_SOURCES(configure_module_dirname + "\\storage\\allocator\\allocators", "createfilemapping.c", "yac"); AC_DEFINE('HAVE_YAC', 1, 'Have yac library'); ADD_FLAG("CFLAGS_YAC", ' /I "' + configure_module_dirname + '" '); } else { WARNING("yac not enabled, headers not found"); } } yac-2.3.1/LICENSE0000664000175000017500000000622214157324055014376 0ustar huixinchenhuixinchen-------------------------------------------------------------------- The PHP License, version 3.01 Copyright (c) 1999 - 2011 The PHP Group. All rights reserved. -------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without modification, is permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name "PHP" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact group@php.net. 4. Products derived from this software may not be called "PHP", nor may "PHP" appear in their name, without prior written permission from group@php.net. You may indicate that your software works in conjunction with PHP by saying "Foo for PHP" instead of calling it "PHP Foo" or "phpfoo" 5. The PHP Group may publish revised and/or new versions of the license from time to time. Each version will be given a distinguishing version number. Once covered code has been published under a particular version of the license, you may always continue to use it under the terms of that version. You may also choose to use such covered code under the terms of any subsequent version of the license published by the PHP Group. No one other than the PHP Group has the right to modify the terms applicable to covered code created under this License. 6. Redistributions of any form whatsoever must retain the following acknowledgment: "This product includes PHP software, freely available from ". THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------- This software consists of voluntary contributions made by many individuals on behalf of the PHP Group. The PHP Group can be contacted via Email at group@php.net. For more information on the PHP Group and the PHP project, please see . PHP includes the Zend Engine, freely available at . yac-2.3.1/CREDITS0000664000175000017500000000003114157324055014401 0ustar huixinchenhuixinchenyac Xinchen Hui Wei Dai yac-2.3.1/config.m40000664000175000017500000001502414157324055015100 0ustar huixinchenhuixinchendnl $Id$ dnl config.m4 for extension yac PHP_ARG_ENABLE(yac, whether to enable yac support, [ --enable-yac Enable yac support]) PHP_ARG_WITH(system-fastlz, whether to use system FastLZ library, [ --with-system-fastlz Use system FastLZ library], no, no) PHP_ARG_ENABLE(json, whether to use igbinary as serializer, [ --enable-json Use igbinary as serializer], no, no) PHP_ARG_ENABLE(msgpack, whether to use msgpack as serializer, [ --enable-msgpack Use Messagepack as serializer], no, no) PHP_ARG_ENABLE(igbinary, whether to use igbinary as serializer, [ --enable-igbinary Use igbinary as serializer], no, no) dnl copied from Zend Optimizer Plus AC_MSG_CHECKING(for sysvipc shared memory support) AC_TRY_RUN([ #include #include #include #include #include #include int main() { pid_t pid; int status; int ipc_id; char *shm; struct shmid_ds shmbuf; ipc_id = shmget(IPC_PRIVATE, 4096, (IPC_CREAT | SHM_R | SHM_W)); if (ipc_id == -1) { return 1; } shm = shmat(ipc_id, NULL, 0); if (shm == (void *)-1) { shmctl(ipc_id, IPC_RMID, NULL); return 2; } if (shmctl(ipc_id, IPC_STAT, &shmbuf) != 0) { shmdt(shm); shmctl(ipc_id, IPC_RMID, NULL); return 3; } shmbuf.shm_perm.uid = getuid(); shmbuf.shm_perm.gid = getgid(); shmbuf.shm_perm.mode = 0600; if (shmctl(ipc_id, IPC_SET, &shmbuf) != 0) { shmdt(shm); shmctl(ipc_id, IPC_RMID, NULL); return 4; } shmctl(ipc_id, IPC_RMID, NULL); strcpy(shm, "hello"); pid = fork(); if (pid < 0) { return 5; } else if (pid == 0) { strcpy(shm, "bye"); return 6; } if (wait(&status) != pid) { return 7; } if (!WIFEXITED(status) || WEXITSTATUS(status) != 6) { return 8; } if (strcmp(shm, "bye") != 0) { return 9; } return 0; } ],dnl AC_DEFINE(HAVE_SHM_IPC, 1, [Define if you have SysV IPC SHM support]) msg=yes,msg=no,msg=no) AC_MSG_RESULT([$msg]) AC_MSG_CHECKING(for mmap() using MAP_ANON shared memory support) AC_TRY_RUN([ #include #include #include #include #include #ifndef MAP_ANON # ifdef MAP_ANONYMOUS # define MAP_ANON MAP_ANONYMOUS # endif #endif #ifndef MAP_FAILED # define MAP_FAILED ((void*)-1) #endif int main() { pid_t pid; int status; char *shm; shm = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); if (shm == MAP_FAILED) { return 1; } strcpy(shm, "hello"); pid = fork(); if (pid < 0) { return 5; } else if (pid == 0) { strcpy(shm, "bye"); return 6; } if (wait(&status) != pid) { return 7; } if (!WIFEXITED(status) || WEXITSTATUS(status) != 6) { return 8; } if (strcmp(shm, "bye") != 0) { return 9; } return 0; } ],dnl AC_DEFINE(HAVE_SHM_MMAP_ANON, 1, [Define if you have mmap(MAP_ANON) SHM support]) msg=yes,msg=no,msg=no) AC_MSG_RESULT([$msg]) AC_MSG_CHECKING(for mmap() using /dev/zero shared memory support) AC_TRY_RUN([ #include #include #include #include #include #include #include #ifndef MAP_FAILED # define MAP_FAILED ((void*)-1) #endif int main() { pid_t pid; int status; int fd; char *shm; fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR); if (fd == -1) { return 1; } shm = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (shm == MAP_FAILED) { return 2; } strcpy(shm, "hello"); pid = fork(); if (pid < 0) { return 5; } else if (pid == 0) { strcpy(shm, "bye"); return 6; } if (wait(&status) != pid) { return 7; } if (!WIFEXITED(status) || WEXITSTATUS(status) != 6) { return 8; } if (strcmp(shm, "bye") != 0) { return 9; } return 0; } ],dnl AC_DEFINE(HAVE_SHM_MMAP_ZERO, 1, [Define if you have mmap("/dev/zero") SHM support]) msg=yes,msg=no,msg=no) AC_MSG_RESULT([$msg]) if test "$PHP_MSGPACK" != "no"; then AC_DEFINE(YAC_ENABLE_MSGPACK, 1, [enable msgpack packager]) ifdef([PHP_ADD_EXTENSION_DEP], [ PHP_ADD_EXTENSION_DEP(yac, msgpack, true) ]) fi if test "$PHP_IGBINARY" != "no"; then AC_DEFINE(YAC_ENABLE_IGBINARY, 1, [enable igbinary packager]) ifdef([PHP_ADD_EXTENSION_DEP], [ PHP_ADD_EXTENSION_DEP(yac, igbinary, true) ]) fi if test "$PHP_JSON" != "no"; then AC_DEFINE(YAC_ENABLE_JSON, 1, [enable json packager]) ifdef([PHP_ADD_EXTENSION_DEP], [ PHP_ADD_EXTENSION_DEP(yac, json, true) ]) fi ifdef([PHP_CHECK_CPU_SUPPORTS], [ if test -x "$PHP_CONFIG"; then php_vernum=`$PHP_CONFIG --vernum` if test $php_vernum -ge 70300; then AC_CHECK_HEADERS([nmmintrin.h]) PHP_CHECK_CPU_SUPPORTS([sse4.2]) dnl Tricky way to remove unintentionally defines if test -e "confdefs.h"; then sed -i "/PHP_HAVE_/d" confdefs.h fi AC_MSG_CHECKING([for crc32 instruction supports]) if test $have_ext_instructions -eq 1; then AC_DEFINE([HAVE_SSE_CRC32], 1, [define if you have sse4.2 crc32 instruction support]) CFLAGS="$CFLAGS -msse4.2" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi fi fi ], []) AC_DEFUN([YAC_BUILTIN_ATOMIC], [ AC_MSG_CHECKING([for __sync_bool_compare_and_swap supports]) AC_LINK_IFELSE([AC_LANG_PROGRAM([], [[ int variable = 1; return (__sync_bool_compare_and_swap(&variable, 1, 2) && __sync_add_and_fetch(&variable, 1)) ? 1 : 0; ]])], [ AC_MSG_RESULT([yes]) AC_DEFINE(HAVE_BUILTIN_ATOMIC, 1, [Define to 1 if gcc supports __sync_bool_compare_and_swap() a.o.]) ], [ AC_MSG_RESULT([no]) ]) ]) YAC_BUILTIN_ATOMIC YAC_FILES="yac.c storage/yac_storage.c storage/allocator/yac_allocator.c storage/allocator/allocators/shm.c storage/allocator/allocators/mmap.c serializer/php.c serializer/msgpack.c serializer/igbinary.c serializer/json.c" if test "$PHP_SYSTEM_FASTLZ" != "no"; then AC_CHECK_HEADERS([fastlz.h]) PHP_CHECK_LIBRARY(fastlz, fastlz_compress, [PHP_ADD_LIBRARY(fastlz, 1, YAC_SHARED_LIBADD)], [AC_MSG_ERROR(FastLZ library not found)]) else YAC_FILES="${YAC_FILES} compressor/fastlz/fastlz.c" fi if test "$PHP_YAC" != "no"; then PHP_SUBST(YAC_SHARED_LIBADD) PHP_NEW_EXTENSION(yac, ${YAC_FILES}, $ext_shared) PHP_ADD_BUILD_DIR([$ext_builddir/storage]) PHP_ADD_BUILD_DIR([$ext_builddir/storage/allocator]) PHP_ADD_BUILD_DIR([$ext_builddir/storage/allocator/allocators]) PHP_ADD_BUILD_DIR([$ext_builddir/serializer]) PHP_ADD_BUILD_DIR([$ext_builddir/compressor]) PHP_ADD_BUILD_DIR([$ext_builddir/compressor/fastlz]) fi yac-2.3.1/yac.c0000664000175000017500000007150514157324055014317 0ustar huixinchenhuixinchen/* +----------------------------------------------------------------------+ | Yet Another Cache | +----------------------------------------------------------------------+ | Copyright (c) 2013-2013 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: Xinchen Hui | +----------------------------------------------------------------------+ */ /* $Id$ */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "php.h" #include "php_ini.h" #include "SAPI.h" #include "ext/standard/info.h" #include "Zend/zend_smart_str.h" #include "Zend/zend_exceptions.h" #include "php_yac.h" #if PHP_MAJOR_VERSION > 7 #include "yac_arginfo.h" #else #include "yac_legacy_arginfo.h" #endif #include "storage/yac_storage.h" #include "serializer/yac_serializer.h" #ifdef HAVE_FASTLZ_H #include #else #include "compressor/fastlz/fastlz.h" #endif zend_class_entry *yac_class_ce; static zend_object_handlers yac_obj_handlers; typedef struct { unsigned char prefix[YAC_STORAGE_MAX_KEY_LEN]; uint16_t prefix_len; zend_object std; } yac_object; ZEND_DECLARE_MODULE_GLOBALS(yac); static yac_serializer_t yac_serializer; static yac_unserializer_t yac_unserializer; static PHP_INI_MH(OnChangeKeysMemoryLimit) /* {{{ */ { if (new_value) { YAC_G(k_msize) = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); } return SUCCESS; } /* }}} */ static PHP_INI_MH(OnChangeValsMemoryLimit) /* {{{ */ { if (new_value) { YAC_G(v_msize) = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); } return SUCCESS; } /* }}} */ static PHP_INI_MH(OnChangeCompressThreshold) /* {{{ */ { if (new_value) { YAC_G(compress_threshold) = zend_atol(ZSTR_VAL(new_value), ZSTR_LEN(new_value)); if (YAC_G(compress_threshold) < YAC_MIN_COMPRESS_THRESHOLD) { YAC_G(compress_threshold) = YAC_MIN_COMPRESS_THRESHOLD; } } return SUCCESS; } /* }}} */ /* {{{ PHP_INI */ PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("yac.enable", "1", PHP_INI_SYSTEM, OnUpdateBool, enable, zend_yac_globals, yac_globals) STD_PHP_INI_BOOLEAN("yac.debug", "0", PHP_INI_ALL, OnUpdateBool, debug, zend_yac_globals, yac_globals) STD_PHP_INI_ENTRY("yac.keys_memory_size", "4M", PHP_INI_SYSTEM, OnChangeKeysMemoryLimit, k_msize, zend_yac_globals, yac_globals) STD_PHP_INI_ENTRY("yac.values_memory_size", "64M", PHP_INI_SYSTEM, OnChangeValsMemoryLimit, v_msize, zend_yac_globals, yac_globals) STD_PHP_INI_ENTRY("yac.compress_threshold", "-1", PHP_INI_SYSTEM, OnChangeCompressThreshold, compress_threshold, zend_yac_globals, yac_globals) STD_PHP_INI_ENTRY("yac.enable_cli", "0", PHP_INI_SYSTEM, OnUpdateBool, enable_cli, zend_yac_globals, yac_globals) STD_PHP_INI_ENTRY("yac.serializer", "php", PHP_INI_SYSTEM, OnUpdateString, serializer, zend_yac_globals, yac_globals) PHP_INI_END() /* }}} */ #define Z_YACOBJ_P(zv) (php_yac_fetch_object(Z_OBJ_P(zv))) static inline yac_object *php_yac_fetch_object(zend_object *obj) /* {{{ */ { return (yac_object *)((char*)(obj) - XtOffsetOf(yac_object, std)); } /* }}} */ static const char *yac_assemble_key(yac_object *yac, zend_string *name, size_t *len) /* {{{ */ { const char *key; if ((ZSTR_LEN(name) + yac->prefix_len) > YAC_STORAGE_MAX_KEY_LEN) { php_error_docref(NULL, E_WARNING, "Key '%.*s%s' exceed max key length '%d' bytes", yac->prefix_len, yac->prefix, ZSTR_VAL(name), YAC_STORAGE_MAX_KEY_LEN); return NULL; } if (yac->prefix_len) { memcpy(yac->prefix + yac->prefix_len, ZSTR_VAL(name), ZSTR_LEN(name)); key = (const char*)yac->prefix; *len = yac->prefix_len + ZSTR_LEN(name); } else { key = ZSTR_VAL(name); *len = ZSTR_LEN(name); } return key; } /* }}} */ static int yac_add_impl(yac_object *yac, zend_string *name, zval *value, int ttl, int add) /* {{{ */ { int ret = 0, flag = Z_TYPE_P(value); char *msg; time_t tv; const char *key; size_t key_len; if ((key = yac_assemble_key(yac, name, &key_len)) == NULL) { return ret; } tv = time(NULL); switch (Z_TYPE_P(value)) { case IS_NULL: case IS_TRUE: case IS_FALSE: ret = yac_storage_update(key, key_len, (char *)&flag, sizeof(int), flag, ttl, add, tv); break; case IS_LONG: ret = yac_storage_update(key, key_len, (char *)&Z_LVAL_P(value), sizeof(long), flag, ttl, add, tv); break; case IS_DOUBLE: ret = yac_storage_update(key, key_len, (char *)&Z_DVAL_P(value), sizeof(double), flag, ttl, add, tv); break; case IS_STRING: #ifdef IS_CONSTANT case IS_CONSTANT: #endif { if (Z_STRLEN_P(value) > YAC_G(compress_threshold) || Z_STRLEN_P(value) > YAC_STORAGE_MAX_ENTRY_LEN) { int compressed_len; char *compressed; /* if longer than this, then we can not stored the length in flag */ if (Z_STRLEN_P(value) > YAC_ENTRY_MAX_ORIG_LEN) { php_error_docref(NULL, E_WARNING, "Value is too long(%ld bytes) to be stored", Z_STRLEN_P(value)); return ret; } compressed = emalloc(Z_STRLEN_P(value) * 1.05); compressed_len = fastlz_compress(Z_STRVAL_P(value), Z_STRLEN_P(value), compressed); if (!compressed_len || compressed_len > Z_STRLEN_P(value)) { php_error_docref(NULL, E_WARNING, "Compression failed"); efree(compressed); return ret; } if (compressed_len > YAC_STORAGE_MAX_ENTRY_LEN) { php_error_docref(NULL, E_WARNING, "Value is too long(%ld bytes) to be stored", Z_STRLEN_P(value)); efree(compressed); return ret; } flag |= YAC_ENTRY_COMPRESSED; flag |= (Z_STRLEN_P(value) << YAC_ENTRY_ORIG_LEN_SHIT); ret = yac_storage_update(key, key_len, compressed, compressed_len, flag, ttl, add, tv); efree(compressed); } else { ret = yac_storage_update(key, key_len, Z_STRVAL_P(value), Z_STRLEN_P(value), flag, ttl, add, tv); } } break; case IS_ARRAY: #ifdef IS_CONSTANT_ARRAY case IS_CONSTANT_ARRAY: #endif case IS_OBJECT: { smart_str buf = {0}; if (yac_serializer(value, &buf, &msg)) { if (buf.s->len > YAC_G(compress_threshold) || buf.s->len > YAC_STORAGE_MAX_ENTRY_LEN) { int compressed_len; char *compressed; if (buf.s->len > YAC_ENTRY_MAX_ORIG_LEN) { php_error_docref(NULL, E_WARNING, "Value is too big to be stored"); return ret; } compressed = emalloc(buf.s->len * 1.05); compressed_len = fastlz_compress(ZSTR_VAL(buf.s), ZSTR_LEN(buf.s), compressed); if (!compressed_len || compressed_len > buf.s->len) { php_error_docref(NULL, E_WARNING, "Compression failed"); efree(compressed); return ret; } if (compressed_len > YAC_STORAGE_MAX_ENTRY_LEN) { php_error_docref(NULL, E_WARNING, "Value is too big to be stored"); efree(compressed); return ret; } flag |= YAC_ENTRY_COMPRESSED; flag |= (buf.s->len << YAC_ENTRY_ORIG_LEN_SHIT); ret = yac_storage_update(key, key_len, compressed, compressed_len, flag, ttl, add, tv); efree(compressed); } else { ret = yac_storage_update(key, key_len, ZSTR_VAL(buf.s), ZSTR_LEN(buf.s), flag, ttl, add, tv); } smart_str_free(&buf); } else { php_error_docref(NULL, E_WARNING, "Serialization failed"); smart_str_free(&buf); } } break; case IS_RESOURCE: php_error_docref(NULL, E_WARNING, "Type 'IS_RESOURCE' cannot be stored"); break; default: php_error_docref(NULL, E_WARNING, "Unsupported valued type to be stored '%d'", flag); break; } return ret; } /* }}} */ static int yac_add_multi_impl(yac_object *yac, zval *kvs, int ttl, int add) /* {{{ */ { HashTable *ht = Z_ARRVAL_P(kvs); zend_string *key; zend_ulong idx; zval *value; ZEND_HASH_FOREACH_KEY_VAL(ht, idx, key, value) { uint32_t should_free = 0; if (!key) { key = strpprintf(0, "%lu", idx); should_free = 1; } if (yac_add_impl(yac, key, value, ttl, add)) { if (should_free) { zend_string_release(key); } continue; } else { if (should_free) { zend_string_release(key); } return 0; } } ZEND_HASH_FOREACH_END(); return 1; } /* }}} */ static zval* yac_get_impl(yac_object *yac, zend_string *name, uint32_t *cas, zval *rv) /* {{{ */ { uint32_t flag, size = 0; char *data, *msg; time_t tv; const char *key; size_t key_len; if ((key = yac_assemble_key(yac, name, &key_len)) == NULL) { return NULL; } tv = time(NULL); if (yac_storage_find(key, key_len, &data, &size, &flag, (int *)cas, tv)) { switch ((flag & YAC_ENTRY_TYPE_MASK)) { case IS_NULL: if (size == sizeof(int)) { ZVAL_NULL(rv); } efree(data); break; case IS_TRUE: if (size == sizeof(int)) { ZVAL_TRUE(rv); } efree(data); break; case IS_FALSE: if (size == sizeof(int)) { ZVAL_FALSE(rv); } efree(data); break; case IS_LONG: if (size == sizeof(long)) { ZVAL_LONG(rv, *(long*)data); } efree(data); break; case IS_DOUBLE: if (size == sizeof(double)) { ZVAL_DOUBLE(rv, *(double*)data); } efree(data); break; case IS_STRING: #ifdef IS_CONSTANT case IS_CONSTANT: #endif { if ((flag & YAC_ENTRY_COMPRESSED)) { size_t orig_len = ((uint32_t)flag >> YAC_ENTRY_ORIG_LEN_SHIT); char *origin = emalloc(orig_len + 1); uint32_t length; length = fastlz_decompress(data, size, origin, orig_len); if (!length) { php_error_docref(NULL, E_WARNING, "Decompression failed"); efree(data); efree(origin); return NULL; } ZVAL_STRINGL(rv, origin, length); efree(origin); efree(data); } else { ZVAL_STRINGL(rv, data, size); efree(data); } } break; case IS_ARRAY: #ifdef IS_CONSTANT_ARRAY case IS_CONSTANT_ARRAY: #endif case IS_OBJECT: { if ((flag & YAC_ENTRY_COMPRESSED)) { size_t length, orig_len = ((uint32_t)flag >> YAC_ENTRY_ORIG_LEN_SHIT); char *origin = emalloc(orig_len + 1); length = fastlz_decompress(data, size, origin, orig_len); if (!length) { php_error_docref(NULL, E_WARNING, "Decompression failed"); efree(data); efree(origin); return NULL; } efree(data); data = origin; size = length; } rv = yac_unserializer(data, size, &msg, rv); efree(data); } break; default: php_error_docref(NULL, E_WARNING, "Unexpected valued type '%d'", flag); rv = NULL; break; } } else { rv = NULL; } return rv; } /* }}} */ static zval* yac_get_multi_impl(yac_object *yac, zval *keys, zval *cas, zval *rv) /* {{{ */ { zval *value; HashTable *ht = Z_ARRVAL_P(keys); array_init(rv); ZEND_HASH_FOREACH_VAL(ht, value) { uint32_t lcas = 0; zval *v, tmp; switch (Z_TYPE_P(value)) { case IS_STRING: if ((v = yac_get_impl(yac, Z_STR_P(value), &lcas, &tmp))) { zend_symtable_update(Z_ARRVAL_P(rv), Z_STR_P(value), v); } else { ZVAL_FALSE(&tmp); zend_symtable_update(Z_ARRVAL_P(rv), Z_STR_P(value), &tmp); } continue; default: { zend_string *key = zval_get_string(value); if ((v = yac_get_impl(yac, key, &lcas, &tmp))) { zend_symtable_update(Z_ARRVAL_P(rv), key, v); } else { ZVAL_FALSE(&tmp); zend_symtable_update(Z_ARRVAL_P(rv), key, &tmp); } zend_string_release(key); } continue; } } ZEND_HASH_FOREACH_END(); return rv; } /* }}} */ static int yac_delete_impl(yac_object *yac, zend_string *name, int ttl) /* {{{ */ { time_t tv = 0; const char *key; size_t key_len; if ((key = yac_assemble_key(yac, name, &key_len)) == NULL) { return 0; } if (ttl) { tv = (zend_ulong)time(NULL); } return yac_storage_delete(key, key_len, ttl, tv); } /* }}} */ static int yac_delete_multi_impl(yac_object *yac, zval *keys, int ttl) /* {{{ */ { HashTable *ht = Z_ARRVAL_P(keys); int ret = 1; zval *value; ZEND_HASH_FOREACH_VAL(ht, value) { switch (Z_TYPE_P(value)) { case IS_STRING: ret = ret & yac_delete_impl(yac, Z_STR_P(value), ttl); continue; default: { zend_string *key = zval_get_string(value); ret = ret & yac_delete_impl(yac, key, ttl); zend_string_release(key); } continue; } } ZEND_HASH_FOREACH_END(); return ret; } /* }}} */ static zend_object *yac_object_new(zend_class_entry *ce) /* {{{ */ { yac_object *yac = emalloc(sizeof(yac_object) + zend_object_properties_size(ce)); zend_object_std_init(&yac->std, ce); yac->std.handlers = &yac_obj_handlers; yac->prefix_len = 0; return &yac->std; } /* }}} */ static void yac_object_free(zend_object *object) /* {{{ */ { zend_object_std_dtor(object); } /* }}} */ static zval* yac_read_property_ptr(void *zobj, void *name, int type, void **cache_slot) /* {{{ */ { zend_string *member; #if PHP_VERSION_ID < 80000 member = Z_STR_P((zval*)name); #else member = (zend_string*)name; #endif zend_throw_exception_ex(NULL, 0, "Retrieval of Yac->%s for modification is unsupported", ZSTR_VAL(member)); return &EG(error_zval); } /* }}} */ static zval* yac_read_property(void /* for PHP8 compatibility */ *zobj, void *name, int type, void **cache_slot, zval *rv) /* {{{ */ { yac_object *yac; zend_string *member; if (UNEXPECTED(type == BP_VAR_RW||type == BP_VAR_W)) { return &EG(error_zval); } #if PHP_VERSION_ID < 80000 yac = Z_YACOBJ_P((zval*)zobj); member = Z_STR_P((zval*)name); #else yac = php_yac_fetch_object((zend_object*)zobj); member = (zend_string*)name; #endif if (yac_get_impl(yac, member, NULL, rv)) { return rv; } return &EG(uninitialized_zval); } /* }}} */ static YAC_WHANDLER yac_write_property(void *zobj, void *name, zval *value, void **cache_slot) /* {{{ */ { yac_object *yac; zend_string *member; #if PHP_VERSION_ID < 80000 yac = Z_YACOBJ_P((zval*)zobj); member = Z_STR_P((zval*)name); #else yac = php_yac_fetch_object((zend_object*)zobj); member = (zend_string*)name; #endif yac_add_impl(yac, member, value, 0, 0); Z_TRY_ADDREF_P(value); YAC_WHANDLER_RET(value); } /* }}} */ static void yac_unset_property(void *zobj, void *name, void **cache_slot) /* {{{ */ { yac_object *yac; zend_string *member; #if PHP_VERSION_ID < 80000 yac = Z_YACOBJ_P((zval*)zobj); member = Z_STR_P((zval*)name); #else yac = php_yac_fetch_object((zend_object*)zobj); member = (zend_string*)name; #endif yac_delete_impl(yac, member, 0); } /* }}} */ /** {{{ proto public Yac::__construct([string $prefix]) */ PHP_METHOD(yac, __construct) { zend_string *prefix = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S", &prefix) == FAILURE) { return; } if (!YAC_G(enable)) { zend_throw_exception(NULL, "Yac is not enabled", 0); } if (prefix && ZSTR_LEN(prefix)) { yac_object *yac; if (ZSTR_LEN(prefix) > YAC_STORAGE_MAX_KEY_LEN) { zend_throw_exception_ex(NULL, 0, "Prefix '%s' exceed max key length '%d' bytes", ZSTR_VAL(prefix), YAC_STORAGE_MAX_KEY_LEN); return; } yac = Z_YACOBJ_P(getThis()); yac->prefix_len = ZSTR_LEN(prefix); memcpy(yac->prefix, ZSTR_VAL(prefix), ZSTR_LEN(prefix)); } } /* }}} */ /** {{{ proto public Yac::add(mixed $keys, mixed $value[, int $ttl]) */ PHP_METHOD(yac, add) { zend_long ttl = 0; zval *keys, *value = NULL; int ret; switch (ZEND_NUM_ARGS()) { case 1: if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &keys) == FAILURE) { return; } break; case 2: if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &keys, &value) == FAILURE) { return; } if (Z_TYPE_P(keys) == IS_ARRAY) { if (Z_TYPE_P(value) == IS_LONG) { ttl = Z_LVAL_P(value); value = NULL; } else { php_error_docref(NULL, E_WARNING, "ttl parameter must be an integer"); return; } } break; case 3: if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzl", &keys, &value, &ttl) == FAILURE) { return; } break; default: WRONG_PARAM_COUNT; } if (Z_TYPE_P(keys) == IS_ARRAY) { ret = yac_add_multi_impl(Z_YACOBJ_P(getThis()), keys, ttl, 1); } else if (Z_TYPE_P(keys) == IS_STRING) { ret = yac_add_impl(Z_YACOBJ_P(getThis()), Z_STR_P(keys), value, ttl, 1); } else { zend_string *key = zval_get_string(keys); ret = yac_add_impl(Z_YACOBJ_P(getThis()), key, value, ttl, 1); zend_string_release(key); } RETURN_BOOL(ret); } /* }}} */ /** {{{ proto public Yac::set(mixed $keys, mixed $value[, int $ttl]) */ PHP_METHOD(yac, set) { zend_long ttl = 0; zval *keys, *value = NULL; int ret; switch (ZEND_NUM_ARGS()) { case 1: if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &keys) == FAILURE) { return; } break; case 2: if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &keys, &value) == FAILURE) { return; } if (Z_TYPE_P(keys) == IS_ARRAY) { if (Z_TYPE_P(value) == IS_LONG) { ttl = Z_LVAL_P(value); value = NULL; } else { php_error_docref(NULL, E_WARNING, "ttl parameter must be an integer"); return; } } break; case 3: if (zend_parse_parameters(ZEND_NUM_ARGS(), "zzl", &keys, &value, &ttl) == FAILURE) { return; } break; default: WRONG_PARAM_COUNT; } if (Z_TYPE_P(keys) == IS_ARRAY) { ret = yac_add_multi_impl(Z_YACOBJ_P(getThis()), keys, ttl, 0); } else if (Z_TYPE_P(keys) == IS_STRING) { ret = yac_add_impl(Z_YACOBJ_P(getThis()), Z_STR_P(keys), value, ttl, 0); } else { zend_string *key = zval_get_string(keys); ret = yac_add_impl(Z_YACOBJ_P(getThis()), key, value, ttl, 0); zend_string_release(key); } RETURN_BOOL(ret); } /* }}} */ /** {{{ proto public Yac::get(mixed $keys[, int &$cas]) */ PHP_METHOD(yac, get) { uint32_t lcas = 0; zval *ret, *keys, *cas = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|z", &keys, &cas) == FAILURE) { return; } if (Z_TYPE_P(keys) == IS_ARRAY) { ret = yac_get_multi_impl(Z_YACOBJ_P(getThis()), keys, cas, return_value); } else if (Z_TYPE_P(keys) == IS_STRING) { ret = yac_get_impl(Z_YACOBJ_P(getThis()), Z_STR_P(keys), &lcas, return_value); } else { zend_string *key = zval_get_string(keys); ret = yac_get_impl(Z_YACOBJ_P(getThis()), key, &lcas, return_value); zend_string_release(key); } if (ret == NULL) { RETURN_FALSE; } } /* }}} */ /** {{{ proto public Yac::delete(mixed $key[, int $delay = 0]) */ PHP_METHOD(yac, delete) { zend_long time = 0; zval *keys; int ret; if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|l", &keys, &time) == FAILURE) { return; } if (Z_TYPE_P(keys) == IS_ARRAY) { ret = yac_delete_multi_impl(Z_YACOBJ_P(getThis()), keys, time); } else if (Z_TYPE_P(keys) == IS_STRING) { ret = yac_delete_impl(Z_YACOBJ_P(getThis()), Z_STR_P(keys), time); } else { zend_string *key = zval_get_string(keys); ret = yac_delete_impl(Z_YACOBJ_P(getThis()), key, time); zend_string_release(key); } RETURN_BOOL(ret); } /* }}} */ /** {{{ proto public Yac::flush(void) */ PHP_METHOD(yac, flush) { yac_storage_flush(); RETURN_TRUE; } /* }}} */ /** {{{ proto public Yac::info(void) */ PHP_METHOD(yac, info) { yac_storage_info *inf; inf = yac_storage_get_info(); array_init(return_value); add_assoc_long(return_value, "memory_size", inf->k_msize + inf->v_msize); add_assoc_long(return_value, "slots_memory_size", inf->k_msize); add_assoc_long(return_value, "values_memory_size", inf->v_msize); add_assoc_long(return_value, "segment_size", inf->segment_size); add_assoc_long(return_value, "segment_num", inf->segments_num); add_assoc_long(return_value, "miss", inf->miss); add_assoc_long(return_value, "hits", inf->hits); add_assoc_long(return_value, "fails", inf->fails); add_assoc_long(return_value, "kicks", inf->kicks); add_assoc_long(return_value, "recycles", inf->recycles); add_assoc_long(return_value, "slots_size", inf->slots_size); add_assoc_long(return_value, "slots_used", inf->slots_num); yac_storage_free_info(inf); return; } /* }}} */ /** {{{ proto public Yac::dump(int $limit) */ PHP_METHOD(yac, dump) { long limit = 100; yac_item_list *list, *l; array_init(return_value); if (zend_parse_parameters(ZEND_NUM_ARGS(), "|l", &limit) == FAILURE) { return; } list = l = yac_storage_dump(limit); for (; l; l = l->next) { zval item; array_init(&item); add_assoc_long(&item, "index", l->index); add_assoc_long(&item, "hash", l->h); add_assoc_long(&item, "crc", l->crc); add_assoc_long(&item, "ttl", l->ttl); add_assoc_long(&item, "k_len", l->k_len); add_assoc_long(&item, "v_len", l->v_len); add_assoc_long(&item, "size", l->size); add_assoc_string(&item, "key", (char*)l->key); add_next_index_zval(return_value, &item); } yac_storage_free_list(list); return; } /* }}} */ #if 0 only OO-style APIs is supported now /* {{{{ proto bool yac_add(mixed $keys, mixed $value[, int $ttl]) */ PHP_FUNCTION(yac_add) { PHP_MN(yac_add)(INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto bool yac_set(mixed $keys, mixed $value[, int $ttl]) */ PHP_FUNCTION(yac_set) { PHP_MN(yac_set)(INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto bool yac_get(mixed $keys[, int &$cas]) */ PHP_FUNCTION(yac_get) { PHP_MN(yac_get)(INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto bool yac_delete(mixed $keys[, int $delay = 0]) */ PHP_FUNCTION(yac_delete) { PHP_MN(yac_delete)(INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto bool yac_flush(void) */ PHP_FUNCTION(yac_flush) { PHP_MN(yac_flush)(INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ proto bool yac_info(void) */ PHP_FUNCTION(yac_info) { PHP_MN(yac_info)(INTERNAL_FUNCTION_PARAM_PASSTHRU); } /* }}} */ /* {{{ yac_functions[] */ zend_function_entry yac_functions[] = { PHP_FE(yac_add, arginfo_yac_add) PHP_FE(yac_set, arginfo_yac_add) PHP_FE(yac_get, arginfo_yac_get) PHP_FE(yac_delete, arginfo_yac_delete) PHP_FE(yac_flush, arginfo_yac_void) PHP_FE(yac_info, arginfo_yac_void) {NULL, NULL} }; /* }}} */ #endif /** {{{ yac_methods */ zend_function_entry yac_methods[] = { PHP_ME(yac, __construct, arginfo_class_Yac___construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(yac, add, arginfo_class_Yac_add, ZEND_ACC_PUBLIC) PHP_ME(yac, set, arginfo_class_Yac_set, ZEND_ACC_PUBLIC) PHP_ME(yac, get, arginfo_class_Yac_get, ZEND_ACC_PUBLIC) PHP_ME(yac, delete, arginfo_class_Yac_delete, ZEND_ACC_PUBLIC) PHP_ME(yac, flush, arginfo_class_Yac_flush, ZEND_ACC_PUBLIC) PHP_ME(yac, info, arginfo_class_Yac_info, ZEND_ACC_PUBLIC) PHP_ME(yac, dump, arginfo_class_Yac_dump, ZEND_ACC_PUBLIC) {NULL, NULL, NULL} }; /* }}} */ /* {{{ PHP_GINIT_FUNCTION */ PHP_GINIT_FUNCTION(yac) { yac_globals->enable = 1; yac_globals->k_msize = (4 * 1024 * 1024); yac_globals->v_msize = (64 * 1024 * 1024); yac_globals->debug = 0; yac_globals->compress_threshold = -1; yac_globals->enable_cli = 0; #ifdef PHP_WIN32 yac_globals->mmap_base = NULL; #endif } /* }}} */ /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(yac) { char *msg; zend_class_entry ce; REGISTER_INI_ENTRIES(); if (!YAC_G(enable_cli) && !strcmp(sapi_module.name, "cli")) { YAC_G(enable) = 0; } if (YAC_G(enable)) { if (!yac_storage_startup(YAC_G(k_msize), YAC_G(v_msize), &msg)) { php_error(E_ERROR, "Shared memory allocator startup failed at '%s': %s", msg, strerror(errno)); return FAILURE; } } REGISTER_STRINGL_CONSTANT("YAC_VERSION", PHP_YAC_VERSION, sizeof(PHP_YAC_VERSION) - 1, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("YAC_MAX_KEY_LEN", YAC_STORAGE_MAX_KEY_LEN, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("YAC_MAX_VALUE_RAW_LEN", YAC_ENTRY_MAX_ORIG_LEN, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("YAC_MAX_RAW_COMPRESSED_LEN", YAC_STORAGE_MAX_ENTRY_LEN, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("YAC_SERIALIZER_PHP", YAC_SERIALIZER_PHP, CONST_PERSISTENT | CONST_CS); #if YAC_ENABLE_MSGPACK REGISTER_LONG_CONSTANT("YAC_SERIALIZER_MSGPACK", YAC_SERIALIZER_MSGPACK, CONST_PERSISTENT | CONST_CS); #endif #if YAC_ENABLE_IGBINARY REGISTER_LONG_CONSTANT("YAC_SERIALIZER_IGBINARY", YAC_SERIALIZER_IGBINARY, CONST_PERSISTENT | CONST_CS); #endif #if YAC_ENABLE_JSON REGISTER_LONG_CONSTANT("YAC_SERIALIZER_JSON", YAC_SERIALIZER_JSON, CONST_PERSISTENT | CONST_CS); #endif #if YAC_ENABLE_MSGPACK if (strcmp(YAC_G(serializer), "msgpack") == 0) { yac_serializer = yac_serializer_msgpack_pack; yac_unserializer = yac_serializer_msgpack_unpack; REGISTER_LONG_CONSTANT("YAC_SERIALIZER", YAC_SERIALIZER_MSGPACK, CONST_PERSISTENT | CONST_CS); } else #endif #if YAC_ENABLE_IGBINARY if (strcmp(YAC_G(serializer), "igbinary") == 0) { yac_serializer = yac_serializer_igbinary_pack; yac_unserializer = yac_serializer_igbinary_unpack; REGISTER_LONG_CONSTANT("YAC_SERIALIZER", YAC_SERIALIZER_IGBINARY, CONST_PERSISTENT | CONST_CS); } else #endif #if YAC_ENABLE_JSON if (strcmp(YAC_G(serializer), "json") == 0) { yac_serializer = yac_serializer_json_pack; yac_unserializer = yac_serializer_json_unpack; REGISTER_LONG_CONSTANT("YAC_SERIALIZER", YAC_SERIALIZER_JSON, CONST_PERSISTENT | CONST_CS); } else #endif { yac_serializer = yac_serializer_php_pack; yac_unserializer = yac_serializer_php_unpack; REGISTER_LONG_CONSTANT("YAC_SERIALIZER", YAC_SERIALIZER_PHP, CONST_PERSISTENT | CONST_CS); } INIT_CLASS_ENTRY(ce, "Yac", yac_methods); yac_class_ce = zend_register_internal_class(&ce); yac_class_ce->ce_flags |= ZEND_ACC_FINAL; yac_class_ce->create_object = yac_object_new; memcpy(&yac_obj_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); yac_obj_handlers.offset = XtOffsetOf(yac_object, std); yac_obj_handlers.free_obj = yac_object_free; if (YAC_G(enable)) { yac_obj_handlers.read_property = (zend_object_read_property_t)yac_read_property; yac_obj_handlers.write_property = (zend_object_write_property_t)yac_write_property; yac_obj_handlers.unset_property = (zend_object_unset_property_t)yac_unset_property; yac_obj_handlers.get_property_ptr_ptr = (zend_object_get_property_ptr_ptr_t)yac_read_property_ptr; } return SUCCESS; } /* }}} */ /* {{{ PHP_MSHUTDOWN_FUNCTION */ PHP_MSHUTDOWN_FUNCTION(yac) { UNREGISTER_INI_ENTRIES(); if (YAC_G(enable)) { yac_storage_shutdown(); } return SUCCESS; } /* }}} */ /* {{{ PHP_MINFO_FUNCTION */ PHP_MINFO_FUNCTION(yac) { smart_str names = {0,}; php_info_print_table_start(); php_info_print_table_header(2, "yac support", "enabled"); php_info_print_table_row(2, "Version", PHP_YAC_VERSION); php_info_print_table_row(2, "Shared Memory", yac_storage_shared_memory_name()); smart_str_appends(&names, "php"); #if YAC_ENABLE_MSGPACK smart_str_appends(&names, ", msgpack"); #endif #if YAC_ENABLE_IGBINARY smart_str_appends(&names, ", igbinary"); #endif #if YAC_ENABLE_JSON smart_str_appends(&names, ", json"); #endif php_info_print_table_row(2, "Serializer", ZSTR_VAL(names.s)); smart_str_free(&names); php_info_print_table_end(); DISPLAY_INI_ENTRIES(); if (YAC_G(enable)) { char buf[64]; yac_storage_info *inf; inf = yac_storage_get_info(); php_info_print_table_start(); php_info_print_table_colspan_header(2, "Cache info"); snprintf(buf, sizeof(buf), "%ld", inf->k_msize + inf->v_msize); php_info_print_table_row(2, "Total Shared Memory Usage(memory_size)", buf); snprintf(buf, sizeof(buf), "%ld", inf->k_msize); php_info_print_table_row(2, "Total Shared Memory Usage for keys(keys_memory_size)", buf); snprintf(buf, sizeof(buf), "%ld", inf->v_msize); php_info_print_table_row(2, "Total Shared Memory Usage for values(values_memory_size)", buf); snprintf(buf, sizeof(buf), "%d", inf->segment_size); php_info_print_table_row(2, "Size of Shared Memory Segment(segment_size)", buf); snprintf(buf, sizeof(buf), "%d", inf->segments_num); php_info_print_table_row(2, "Number of Segments (segment_num)", buf); snprintf(buf, sizeof(buf), "%d", inf->slots_size); php_info_print_table_row(2, "Total Slots Number(slots_size)", buf); snprintf(buf, sizeof(buf), "%d", inf->slots_num); php_info_print_table_row(2, "Total Used Slots(slots_num)", buf); php_info_print_table_end(); yac_storage_free_info(inf); } } /* }}} */ #ifdef COMPILE_DL_YAC ZEND_GET_MODULE(yac) #endif static zend_module_dep yac_module_deps[] = { #if YAC_ENABLE_MSGPACK ZEND_MOD_REQUIRED("msgpack") #endif #if YAC_ENABLE_IGBINARY ZEND_MOD_REQUIRED("igbinary") #endif #if YAC_ENABLE_JSON ZEND_MOD_REQUIRED("json") #endif {NULL, NULL, NULL, 0} }; /* {{{ yac_module_entry */ zend_module_entry yac_module_entry = { STANDARD_MODULE_HEADER_EX, NULL, yac_module_deps, "yac", NULL, /* yac_functions, */ PHP_MINIT(yac), PHP_MSHUTDOWN(yac), NULL, NULL, PHP_MINFO(yac), PHP_YAC_VERSION, PHP_MODULE_GLOBALS(yac), PHP_GINIT(yac), NULL, NULL, STANDARD_MODULE_PROPERTIES_EX }; /* }}} */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ yac-2.3.1/php_yac.h0000664000175000017500000000521514157324055015166 0ustar huixinchenhuixinchen/* +----------------------------------------------------------------------+ | Yet Another Cache | +----------------------------------------------------------------------+ | Copyright (c) 2013-2013 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: Xinchen Hui | +----------------------------------------------------------------------+ */ /* $Id$ */ #ifndef PHP_YAC_H #define PHP_YAC_H extern zend_module_entry yac_module_entry; #define phpext_yac_ptr &yac_module_entry #ifdef PHP_WIN32 #define PHP_YAC_API __declspec(dllexport) #else #define PHP_YAC_API #endif #ifdef ZTS #include "TSRM.h" #endif #define PHP_YAC_VERSION "2.3.1" #if PHP_VERSION_ID < 70400 #define YAC_WHANDLER void #define YAC_WHANDLER_RET(zv) return #else #define YAC_WHANDLER zval * #define YAC_WHANDLER_RET(zv) return zv #endif #define YAC_CLASS_PROPERTY_PREFIX "_prefix" #define YAC_ENTRY_COMPRESSED 0x0020 #define YAC_ENTRY_TYPE_MASK 0x1f #define YAC_ENTRY_ORIG_LEN_SHIT 6 #define YAC_ENTRY_MAX_ORIG_LEN ((1U << ((sizeof(int)*8 - YAC_ENTRY_ORIG_LEN_SHIT))) - 1) #define YAC_MIN_COMPRESS_THRESHOLD 1024 #define YAC_SERIALIZER_PHP 0 #define YAC_SERIALIZER_JSON 1 #define YAC_SERIALIZER_MSGPACK 2 #define YAC_SERIALIZER_IGBINARY 3 ZEND_BEGIN_MODULE_GLOBALS(yac) zend_bool enable; zend_bool debug; size_t k_msize; size_t v_msize; zend_ulong compress_threshold; zend_bool enable_cli; char *serializer; #ifdef PHP_WIN32 char *mmap_base; #endif ZEND_END_MODULE_GLOBALS(yac) PHP_MINIT_FUNCTION(yac); PHP_MSHUTDOWN_FUNCTION(yac); PHP_RINIT_FUNCTION(yac); PHP_RSHUTDOWN_FUNCTION(yac); PHP_MINFO_FUNCTION(yac); ZEND_EXTERN_MODULE_GLOBALS(yac); #define YAC_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(yac, v) #endif /* PHP_YAC_H */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */ yac-2.3.1/yac_arginfo.h0000664000175000017500000000264714157324055016032 0ustar huixinchenhuixinchen/* This is a generated file, edit the .stub.php file instead. * Stub hash: 0b50242ac2a8f06b2a78418f81c37ac715561053 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Yac___construct, 0, 0, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, prefix, IS_STRING, 0, "\"\"") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Yac_add, 0, 2, _IS_BOOL, 1) ZEND_ARG_TYPE_MASK(0, key, MAY_BE_STRING|MAY_BE_ARRAY, NULL) ZEND_ARG_TYPE_INFO(0, value, IS_MIXED, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, ttl, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Yac_get, 0, 1, _IS_BOOL, 1) ZEND_ARG_TYPE_MASK(0, key, MAY_BE_STRING|MAY_BE_ARRAY, NULL) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(1, cas, IS_MIXED, 0, "NULL") ZEND_END_ARG_INFO() #define arginfo_class_Yac_set arginfo_class_Yac_add ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Yac_delete, 0, 1, _IS_BOOL, 1) ZEND_ARG_TYPE_MASK(0, key, MAY_BE_STRING|MAY_BE_ARRAY, NULL) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, delay, IS_LONG, 0, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Yac_flush, 0, 0, _IS_BOOL, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Yac_info, 0, 0, IS_ARRAY, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Yac_dump, 0, 0, IS_ARRAY, 1) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, limit, IS_LONG, 0, "0") ZEND_END_ARG_INFO() yac-2.3.1/yac_legacy_arginfo.h0000664000175000017500000000162314157324055017347 0ustar huixinchenhuixinchen/* This is a generated file, edit the .stub.php file instead. * Stub hash: 0b50242ac2a8f06b2a78418f81c37ac715561053 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Yac___construct, 0, 0, 0) ZEND_ARG_INFO(0, prefix) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Yac_add, 0, 0, 2) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, value) ZEND_ARG_INFO(0, ttl) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Yac_get, 0, 0, 1) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(1, cas) ZEND_END_ARG_INFO() #define arginfo_class_Yac_set arginfo_class_Yac_add ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Yac_delete, 0, 0, 1) ZEND_ARG_INFO(0, key) ZEND_ARG_INFO(0, delay) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Yac_flush, 0, 0, 0) ZEND_END_ARG_INFO() #define arginfo_class_Yac_info arginfo_class_Yac_flush ZEND_BEGIN_ARG_INFO_EX(arginfo_class_Yac_dump, 0, 0, 0) ZEND_ARG_INFO(0, limit) ZEND_END_ARG_INFO()