zend_bool apc_fcntl_nonblocking_lock(int fd) { if(lock_reg(fd, F_SETLK, F_WRLCK, 0, SEEK_SET, 0) < 0) { if(errno==EACCES||errno==EAGAIN) return 0; else apc_eprint("apc_fcntl_lock failed:"); } return 1; }
int apc_fcntl_create(const char* pathname) { int fd; if(pathname == NULL) { char lock_path[] = "/tmp/.apc.XXXXXX"; mktemp(lock_path); fd = open(lock_path, O_RDWR|O_CREAT, 0666); if(fd > 0 ) { unlink(lock_path); return fd; } else { apc_eprint("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", lock_path); return -1; } } fd = open(pathname, O_RDWR|O_CREAT, 0666); if(fd > 0 ) { unlink(pathname); return fd; } apc_eprint("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", pathname); return -1; }
apc_segment_t apc_mmap(char *file_mask, size_t size) { apc_segment_t segment; int fd = -1; int flags = MAP_SHARED | MAP_NOSYNC; int remap = 1; /* If no filename was provided, do an anonymous mmap */ if(!file_mask || (file_mask && !strlen(file_mask))) { #if !defined(MAP_ANON) apc_eprint("Anonymous mmap does not apear to be available on this system (MAP_ANON/MAP_ANONYMOUS). Please see the apc.mmap_file_mask INI option."); #else fd = -1; flags = MAP_SHARED | MAP_ANON; remap = 0; #endif } else if(!strcmp(file_mask,"/dev/zero")) { fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR); if(fd == -1) { apc_eprint("apc_mmap: open on /dev/zero failed:"); goto error; } remap = 0; /* cannot remap */ } else if(strstr(file_mask,".shm")) { /* * If the filemask contains .shm we try to do a POSIX-compliant shared memory * backed mmap which should avoid synchs on some platforms. At least on * FreeBSD this implies MAP_NOSYNC and on Linux it is equivalent of mmap'ing * a file in a mounted shmfs. For this to work on Linux you need to make sure * you actually have shmfs mounted. Also on Linux, make sure the file_mask you * pass in has a leading / and no other /'s. eg. /apc.shm.XXXXXX * On FreeBSD these are mapped onto the regular filesystem so you can put whatever * path you want here. */ if(!mktemp(file_mask)) { apc_eprint("apc_mmap: mktemp on %s failed:", file_mask); goto error; } fd = shm_open(file_mask, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR); if(fd == -1) { apc_eprint("apc_mmap: shm_open on %s failed:", file_mask); goto error; } if (ftruncate(fd, size) < 0) { close(fd); shm_unlink(file_mask); apc_eprint("apc_mmap: ftruncate failed:"); goto error; } shm_unlink(file_mask); } else { /* * Otherwise we do a normal filesystem mmap */ fd = mkstemp(file_mask); if(fd == -1) { apc_eprint("apc_mmap: mkstemp on %s failed:", file_mask); goto error; } if (ftruncate(fd, size) < 0) { close(fd); unlink(file_mask); apc_eprint("apc_mmap: ftruncate failed:"); goto error; } unlink(file_mask); } segment.shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, flags, fd, 0); #ifdef APC_MEMPROTECT if(remap) { segment.roaddr = (void *)mmap(NULL, size, PROT_READ, flags, fd, 0); } else { segment.roaddr = NULL; } #endif if((long)segment.shmaddr == -1) { apc_eprint("apc_mmap: mmap failed:"); } if(fd != -1) close(fd); return segment; error: segment.shmaddr = (void*)-1; #ifdef APC_MEMPROTECT segment.roaddr = NULL; #endif return segment; }
void apc_fcntl_rdlock(int fd) { if(lock_reg(fd, F_SETLKW, F_RDLCK, 0, SEEK_SET, 0) < 0) { apc_eprint("apc_fcntl_rdlock failed:"); } }
/* {{{ apc_iterator_item */ static apc_iterator_item_t* apc_iterator_item_ctor(apc_iterator_t *iterator, slot_t **slot_pp) { zval *zvalue; char md5str[33]; slot_t *slot = *slot_pp; apc_context_t ctxt = {0, }; apc_iterator_item_t *item = ecalloc(1, sizeof(apc_iterator_item_t)); if (slot->key.type == APC_CACHE_KEY_FILE) { /* keys should be unique and with stat=1 we could have multiple files with the same name, so use '<device> <inode>' instead */ #ifdef PHP_WIN32 item->key_len = spprintf(&item->key, 0, "%I64d %I64d", slot->key.data.file.device, slot->key.data.file.inode); #else item->key_len = spprintf(&item->key, 0, "%ld %ld", (ulong)slot->key.data.file.device, (ulong)slot->key.data.file.inode); #endif item->filename_key = estrdup(slot->value->data.file.filename); } else if (slot->key.type == APC_CACHE_KEY_USER) { item->key = estrndup((char*)slot->key.data.user.identifier, slot->key.data.user.identifier_len); item->key_len = slot->key.data.user.identifier_len; item->filename_key = item->key; } else if (slot->key.type == APC_CACHE_KEY_FPFILE) { item->key = estrndup((char*)slot->key.data.fpfile.fullpath, slot->key.data.fpfile.fullpath_len); item->key_len = slot->key.data.fpfile.fullpath_len; } else { apc_eprint("Internal error, invalid entry type."); } ALLOC_INIT_ZVAL(item->value); array_init(item->value); if (APC_ITER_TYPE & iterator->format) { if(slot->value->type == APC_CACHE_ENTRY_FILE) { add_assoc_string(item->value, "type", "file", 1); } else if(slot->value->type == APC_CACHE_ENTRY_USER) { add_assoc_string(item->value, "type", "user", 1); } } if (APC_ITER_FILENAME & iterator->format) { if(slot->value->type == APC_CACHE_ENTRY_FILE) { if (slot->key.type == APC_CACHE_KEY_FILE) { add_assoc_string(item->value, "filename", slot->value->data.file.filename, 1); } else { /* APC_CACHE_FPFILE */ add_assoc_string(item->value, "filename", (char*)slot->key.data.fpfile.fullpath, 1); } } } if (APC_ITER_DEVICE & iterator->format) { if(slot->key.type == APC_CACHE_KEY_FILE) { #ifdef PHP_WIN32 char buf[20]; sprintf(buf, "%I64d", slot->key.data.file.device); add_assoc_string(item->value, "device", buf, 1); #else add_assoc_long(item->value, "device", slot->key.data.file.device); #endif } } if (APC_ITER_INODE & iterator->format) { if(slot->key.type == APC_CACHE_KEY_FILE) { #ifdef PHP_WIN32 char buf[20]; sprintf(buf, "%I64d", slot->key.data.file.device); add_assoc_string(item->value, "device", buf, 1); #else add_assoc_long(item->value, "inode", slot->key.data.file.inode); #endif } } if (APC_ITER_KEY & iterator->format) { add_assoc_stringl(item->value, "key", item->key, item->key_len, 1); } if (APC_ITER_VALUE & iterator->format) { if(slot->value->type == APC_CACHE_ENTRY_USER) { ctxt.pool = apc_pool_create(APC_UNPOOL, apc_php_malloc, apc_php_free, NULL, NULL); ctxt.copy = APC_COPY_OUT_USER; MAKE_STD_ZVAL(zvalue); apc_cache_fetch_zval(zvalue, slot->value->data.user.val, &ctxt); apc_pool_destroy(ctxt.pool); add_assoc_zval(item->value, "value", zvalue); } } if (APC_ITER_MD5 & iterator->format) { if(slot->value->type == APC_CACHE_ENTRY_FILE) { if(slot->key.md5) { make_digest(md5str, slot->key.md5); add_assoc_string(item->value, "md5", md5str, 1); } } } if (APC_ITER_NUM_HITS & iterator->format) { add_assoc_long(item->value, "num_hits", slot->num_hits); } if (APC_ITER_MTIME & iterator->format) { add_assoc_long(item->value, "mtime", slot->key.mtime); } if (APC_ITER_CTIME & iterator->format) { add_assoc_long(item->value, "creation_time", slot->creation_time); } if (APC_ITER_DTIME & iterator->format) { add_assoc_long(item->value, "deletion_time", slot->deletion_time); } if (APC_ITER_ATIME & iterator->format) { add_assoc_long(item->value, "access_time", slot->access_time); } if (APC_ITER_REFCOUNT & iterator->format) { add_assoc_long(item->value, "ref_count", slot->value->ref_count); } if (APC_ITER_MEM_SIZE & iterator->format) { add_assoc_long(item->value, "mem_size", slot->value->mem_size); } if (APC_ITER_TTL & iterator->format) { if(slot->value->type == APC_CACHE_ENTRY_USER) { add_assoc_long(item->value, "ttl", slot->value->data.user.ttl); } } return item; }