Init Repo

This commit is contained in:
root
2019-09-06 23:53:10 +08:00
commit f0ef89dfbb
7905 changed files with 914138 additions and 0 deletions

174
vendor/swoole/src/memory/Buffer.c vendored Executable file
View File

@@ -0,0 +1,174 @@
/*
+----------------------------------------------------------------------+
| Swoole |
+----------------------------------------------------------------------+
| This source file is subject to version 2.0 of the Apache 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.apache.org/licenses/LICENSE-2.0.html |
| If you did not receive a copy of the Apache2.0 license and are unable|
| to obtain it through the world-wide-web, please send a note to |
| license@swoole.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
+----------------------------------------------------------------------+
*/
#include "swoole.h"
#include "buffer.h"
/**
* create new buffer
*/
swBuffer* swBuffer_new(int trunk_size)
{
swBuffer *buffer = sw_malloc(sizeof(swBuffer));
if (buffer == NULL)
{
swWarn("malloc for buffer failed. Error: %s[%d]", strerror(errno), errno);
return NULL;
}
bzero(buffer, sizeof(swBuffer));
buffer->trunk_size = trunk_size;
return buffer;
}
/**
* create new trunk
*/
swBuffer_trunk *swBuffer_new_trunk(swBuffer *buffer, uint32_t type, uint32_t size)
{
swBuffer_trunk *chunk = sw_malloc(sizeof(swBuffer_trunk));
if (chunk == NULL)
{
swWarn("malloc for trunk failed. Error: %s[%d]", strerror(errno), errno);
return NULL;
}
bzero(chunk, sizeof(swBuffer_trunk));
//require alloc memory
if (type == SW_CHUNK_DATA && size > 0)
{
void *buf = sw_malloc(size);
if (buf == NULL)
{
swWarn("malloc(%d) for data failed. Error: %s[%d]", size, strerror(errno), errno);
sw_free(chunk);
return NULL;
}
chunk->size = size;
chunk->store.ptr = buf;
}
chunk->type = type;
buffer->trunk_num ++;
if (buffer->head == NULL)
{
buffer->tail = buffer->head = chunk;
}
else
{
buffer->tail->next = chunk;
buffer->tail = chunk;
}
return chunk;
}
/**
* pop the head chunk
*/
void swBuffer_pop_trunk(swBuffer *buffer, swBuffer_trunk *chunk)
{
if (chunk->next == NULL)
{
buffer->head = NULL;
buffer->tail = NULL;
buffer->length = 0;
buffer->trunk_num = 0;
}
else
{
buffer->head = chunk->next;
buffer->length -= chunk->length;
buffer->trunk_num--;
}
if (chunk->type == SW_CHUNK_DATA)
{
sw_free(chunk->store.ptr);
}
if (chunk->destroy)
{
chunk->destroy(chunk);
}
sw_free(chunk);
}
/**
* free buffer
*/
int swBuffer_free(swBuffer *buffer)
{
volatile swBuffer_trunk *chunk = buffer->head;
void * *will_free_trunk; //free the point
while (chunk != NULL)
{
if (chunk->type == SW_CHUNK_DATA)
{
sw_free(chunk->store.ptr);
}
will_free_trunk = (void *) chunk;
chunk = chunk->next;
sw_free(will_free_trunk);
}
sw_free(buffer);
return SW_OK;
}
/**
* append to buffer queue
*/
int swBuffer_append(swBuffer *buffer, void *data, uint32_t size)
{
swBuffer_trunk *chunk = swBuffer_new_trunk(buffer, SW_CHUNK_DATA, size);
if (chunk == NULL)
{
return SW_ERR;
}
buffer->length += size;
chunk->length = size;
memcpy(chunk->store.ptr, data, size);
swTraceLog(SW_TRACE_BUFFER, "trunk_n=%d|size=%d|trunk_len=%d|trunk=%p", buffer->trunk_num, size,
chunk->length, chunk);
return SW_OK;
}
/**
* print buffer
*/
void swBuffer_debug(swBuffer *buffer, int print_data)
{
int i = 0;
volatile swBuffer_trunk *trunk = buffer->head;
printf("%s\n%s\n", SW_START_LINE, __func__);
while (trunk != NULL)
{
i++;
printf("%d.\tlen=%d", i, trunk->length);
if (print_data)
{
printf("\tdata=%s", (char *) trunk->store.ptr);
}
printf("\n");
trunk = trunk->next;
}
printf("%s\n%s\n", SW_END_LINE, __func__);
}

249
vendor/swoole/src/memory/FixedPool.c vendored Executable file
View File

@@ -0,0 +1,249 @@
/*
+----------------------------------------------------------------------+
| Swoole |
+----------------------------------------------------------------------+
| This source file is subject to version 2.0 of the Apache 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.apache.org/licenses/LICENSE-2.0.html |
| If you did not receive a copy of the Apache2.0 license and are unable|
| to obtain it through the world-wide-web, please send a note to |
| license@swoole.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
+----------------------------------------------------------------------+
*/
#include "swoole.h"
static void swFixedPool_init(swFixedPool *object);
static void* swFixedPool_alloc(swMemoryPool *pool, uint32_t size);
static void swFixedPool_free(swMemoryPool *pool, void *ptr);
static void swFixedPool_destroy(swMemoryPool *pool);
void swFixedPool_debug_slice(swFixedPool_slice *slice);
/**
* create new FixedPool, random alloc/free fixed size memory
*/
swMemoryPool* swFixedPool_new(uint32_t slice_num, uint32_t slice_size, uint8_t shared)
{
size_t size = slice_size * slice_num + slice_num * sizeof(swFixedPool_slice);
size_t alloc_size = size + sizeof(swFixedPool) + sizeof(swMemoryPool);
void *memory = (shared == 1) ? sw_shm_malloc(alloc_size) : sw_malloc(alloc_size);
swFixedPool *object = memory;
memory += sizeof(swFixedPool);
bzero(object, sizeof(swFixedPool));
object->shared = shared;
object->slice_num = slice_num;
object->slice_size = slice_size;
object->size = size;
swMemoryPool *pool = memory;
memory += sizeof(swMemoryPool);
pool->object = object;
pool->alloc = swFixedPool_alloc;
pool->free = swFixedPool_free;
pool->destroy = swFixedPool_destroy;
object->memory = memory;
/**
* init linked list
*/
swFixedPool_init(object);
return pool;
}
/**
* create new FixedPool, Using the given memory
*/
swMemoryPool* swFixedPool_new2(uint32_t slice_size, void *memory, size_t size)
{
swFixedPool *object = memory;
memory += sizeof(swFixedPool);
bzero(object, sizeof(swFixedPool));
object->slice_size = slice_size;
object->size = size - sizeof(swMemoryPool) - sizeof(swFixedPool);
object->slice_num = object->size / (slice_size + sizeof(swFixedPool_slice));
swMemoryPool *pool = memory;
memory += sizeof(swMemoryPool);
bzero(pool, sizeof(swMemoryPool));
pool->object = object;
pool->alloc = swFixedPool_alloc;
pool->free = swFixedPool_free;
pool->destroy = swFixedPool_destroy;
object->memory = memory;
/**
* init linked list
*/
swFixedPool_init(object);
return pool;
}
/**
* linked list
*/
static void swFixedPool_init(swFixedPool *object)
{
swFixedPool_slice *slice;
void *cur = object->memory;
void *max = object->memory + object->size;
do
{
slice = (swFixedPool_slice *) cur;
bzero(slice, sizeof(swFixedPool_slice));
if (object->head != NULL)
{
object->head->pre = slice;
slice->next = object->head;
}
else
{
object->tail = slice;
}
object->head = slice;
cur += (sizeof(swFixedPool_slice) + object->slice_size);
if (cur < max)
{
slice->pre = (swFixedPool_slice *) cur;
}
else
{
slice->pre = NULL;
break;
}
} while (1);
}
static void* swFixedPool_alloc(swMemoryPool *pool, uint32_t size)
{
swFixedPool *object = pool->object;
swFixedPool_slice *slice;
slice = object->head;
if (slice->lock == 0)
{
slice->lock = 1;
object->slice_use ++;
/**
* move next slice to head (idle list)
*/
object->head = slice->next;
slice->next->pre = NULL;
/*
* move this slice to tail (busy list)
*/
object->tail->next = slice;
slice->next = NULL;
slice->pre = object->tail;
object->tail = slice;
return slice->data;
}
else
{
return NULL;
}
}
static void swFixedPool_free(swMemoryPool *pool, void *ptr)
{
swFixedPool *object = pool->object;
swFixedPool_slice *slice;
assert(ptr > object->memory && ptr < object->memory + object->size);
slice = ptr - sizeof(swFixedPool_slice);
if (slice->lock)
{
object->slice_use--;
}
slice->lock = 0;
//list head, AB
if (slice->pre == NULL)
{
return;
}
//list tail, DE
if (slice->next == NULL)
{
slice->pre->next = NULL;
object->tail = slice->pre;
}
//middle BCD
else
{
slice->pre->next = slice->next;
slice->next->pre = slice->pre;
}
slice->pre = NULL;
slice->next = object->head;
object->head->pre = slice;
object->head = slice;
}
static void swFixedPool_destroy(swMemoryPool *pool)
{
swFixedPool *object = pool->object;
if (object->shared)
{
sw_shm_free(object);
}
else
{
sw_free(object);
}
}
void swFixedPool_debug(swMemoryPool *pool)
{
int line = 0;
swFixedPool *object = pool->object;
swFixedPool_slice *slice = object->head;
printf("===============================%s=================================\n", __FUNCTION__);
while (slice != NULL)
{
if (slice->next == slice)
{
printf("-------------------@@@@@@@@@@@@@@@@@@@@@@----------------\n");
}
printf("#%d\t", line);
swFixedPool_debug_slice(slice);
slice = slice->next;
line++;
if (line > 100)
break;
}
}
void swFixedPool_debug_slice(swFixedPool_slice *slice)
{
printf("Slab[%p]\t", slice);
printf("pre=%p\t", slice->pre);
printf("next=%p\t", slice->next);
printf("tag=%d\t", slice->lock);
printf("data=%p\n", slice->data);
}

50
vendor/swoole/src/memory/Malloc.c vendored Executable file
View File

@@ -0,0 +1,50 @@
/*
+----------------------------------------------------------------------+
| Swoole |
+----------------------------------------------------------------------+
| This source file is subject to version 2.0 of the Apache 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.apache.org/licenses/LICENSE-2.0.html |
| If you did not receive a copy of the Apache2.0 license and are unable|
| to obtain it through the world-wide-web, please send a note to |
| license@swoole.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
+----------------------------------------------------------------------+
*/
#include "swoole.h"
static void* swMalloc_alloc(swMemoryPool *pool, uint32_t size);
static void swMalloc_free(swMemoryPool *pool, void *ptr);
static void swMalloc_destroy(swMemoryPool *pool);
swMemoryPool* swMalloc_new()
{
swMemoryPool *pool = sw_malloc(sizeof(swMemoryPool));
if (pool == NULL)
{
swSysError("mallc(%ld) failed.", sizeof(swMemoryPool));
return NULL;
}
pool->alloc = swMalloc_alloc;
pool->free = swMalloc_free;
pool->destroy = swMalloc_destroy;
return pool;
}
static void* swMalloc_alloc(swMemoryPool *pool, uint32_t size)
{
return sw_malloc(size);
}
static void swMalloc_free(swMemoryPool *pool, void *ptr)
{
sw_free(ptr);
}
static void swMalloc_destroy(swMemoryPool *pool)
{
sw_free(pool);
}

143
vendor/swoole/src/memory/MemoryGlobal.c vendored Executable file
View File

@@ -0,0 +1,143 @@
/*
+----------------------------------------------------------------------+
| Swoole |
+----------------------------------------------------------------------+
| This source file is subject to version 2.0 of the Apache 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.apache.org/licenses/LICENSE-2.0.html |
| If you did not receive a copy of the Apache2.0 license and are unable|
| to obtain it through the world-wide-web, please send a note to |
| license@swoole.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
+----------------------------------------------------------------------+
*/
#include "swoole.h"
#define SW_MIN_PAGE_SIZE 4096
typedef struct _swMemoryGlobal_page
{
struct _swMemoryGlobal_page *next;
char memory[0];
} swMemoryGlobal_page;
typedef struct _swMemoryGlobal
{
uint8_t shared;
uint32_t pagesize;
swLock lock;
swMemoryGlobal_page *root_page;
swMemoryGlobal_page *current_page;
uint32_t current_offset;
} swMemoryGlobal;
static void *swMemoryGlobal_alloc(swMemoryPool *pool, uint32_t size);
static void swMemoryGlobal_free(swMemoryPool *pool, void *ptr);
static void swMemoryGlobal_destroy(swMemoryPool *poll);
static swMemoryGlobal_page* swMemoryGlobal_new_page(swMemoryGlobal *gm);
swMemoryPool* swMemoryGlobal_new(uint32_t pagesize, uint8_t shared)
{
swMemoryGlobal gm, *gm_ptr;
assert(pagesize >= SW_MIN_PAGE_SIZE);
bzero(&gm, sizeof(swMemoryGlobal));
gm.shared = shared;
gm.pagesize = pagesize;
swMemoryGlobal_page *page = swMemoryGlobal_new_page(&gm);
if (page == NULL)
{
return NULL;
}
if (swMutex_create(&gm.lock, shared) < 0)
{
return NULL;
}
gm.root_page = page;
gm_ptr = (swMemoryGlobal *) page->memory;
gm.current_offset += sizeof(swMemoryGlobal);
swMemoryPool *allocator = (swMemoryPool *) (page->memory + gm.current_offset);
gm.current_offset += sizeof(swMemoryPool);
allocator->object = gm_ptr;
allocator->alloc = swMemoryGlobal_alloc;
allocator->destroy = swMemoryGlobal_destroy;
allocator->free = swMemoryGlobal_free;
memcpy(gm_ptr, &gm, sizeof(gm));
return allocator;
}
static swMemoryGlobal_page* swMemoryGlobal_new_page(swMemoryGlobal *gm)
{
swMemoryGlobal_page *page = (gm->shared == 1) ? sw_shm_malloc(gm->pagesize) : sw_malloc(gm->pagesize);
if (page == NULL)
{
return NULL;
}
bzero(page, gm->pagesize);
page->next = NULL;
if (gm->current_page != NULL)
{
gm->current_page->next = page;
}
gm->current_page = page;
gm->current_offset = 0;
return page;
}
static void *swMemoryGlobal_alloc(swMemoryPool *pool, uint32_t size)
{
swMemoryGlobal *gm = pool->object;
gm->lock.lock(&gm->lock);
if (size > gm->pagesize - sizeof(swMemoryGlobal_page))
{
swWarn("failed to alloc %d bytes, exceed the maximum size[%d].", size, gm->pagesize - (int) sizeof(swMemoryGlobal_page));
gm->lock.unlock(&gm->lock);
return NULL;
}
if (gm->current_offset + size > gm->pagesize - sizeof(swMemoryGlobal_page))
{
swMemoryGlobal_page *page = swMemoryGlobal_new_page(gm);
if (page == NULL)
{
swWarn("swMemoryGlobal_alloc alloc memory error.");
gm->lock.unlock(&gm->lock);
return NULL;
}
gm->current_page = page;
}
void *mem = gm->current_page->memory + gm->current_offset;
gm->current_offset += size;
gm->lock.unlock(&gm->lock);
return mem;
}
static void swMemoryGlobal_free(swMemoryPool *pool, void *ptr)
{
swWarn("swMemoryGlobal Allocator don't need to release.");
}
static void swMemoryGlobal_destroy(swMemoryPool *poll)
{
swMemoryGlobal *gm = poll->object;
swMemoryGlobal_page *page = gm->root_page;
swMemoryGlobal_page *next;
do
{
next = page->next;
sw_shm_free(page);
page = next;
} while (page);
}

211
vendor/swoole/src/memory/RingBuffer.c vendored Executable file
View File

@@ -0,0 +1,211 @@
/*
+----------------------------------------------------------------------+
| Swoole |
+----------------------------------------------------------------------+
| This source file is subject to version 2.0 of the Apache 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.apache.org/licenses/LICENSE-2.0.html |
| If you did not receive a copy of the Apache2.0 license and are unable|
| to obtain it through the world-wide-web, please send a note to |
| license@swoole.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
+----------------------------------------------------------------------+
*/
#include "swoole.h"
typedef struct
{
uint8_t shared;
uint8_t status;
uint32_t size;
uint32_t alloc_offset;
uint32_t collect_offset;
uint32_t alloc_count;
sw_atomic_t free_count;
void *memory;
} swRingBuffer;
typedef struct
{
uint16_t lock;
uint16_t index;
uint32_t length;
char data[0];
} swRingBuffer_item;
static void swRingBuffer_destory(swMemoryPool *pool);
static void* swRingBuffer_alloc(swMemoryPool *pool, uint32_t size);
static void swRingBuffer_free(swMemoryPool *pool, void *ptr);
#ifdef SW_RINGBUFFER_DEBUG
static void swRingBuffer_print(swRingBuffer *object, char *prefix);
static void swRingBuffer_print(swRingBuffer *object, char *prefix)
{
printf("%s: size=%d, status=%d, alloc_count=%d, free_count=%d, offset=%d, next_offset=%d\n", prefix, object->size,
object->status, object->alloc_count, object->free_count, object->alloc_offset, object->collect_offset);
}
#endif
swMemoryPool *swRingBuffer_new(uint32_t size, uint8_t shared)
{
void *mem = (shared == 1) ? sw_shm_malloc(size) : sw_malloc(size);
if (mem == NULL)
{
swWarn("malloc(%d) failed.", size);
return NULL;
}
swRingBuffer *object = mem;
mem += sizeof(swRingBuffer);
bzero(object, sizeof(swRingBuffer));
object->size = (size - sizeof(swRingBuffer) - sizeof(swMemoryPool));
object->shared = shared;
swMemoryPool *pool = mem;
mem += sizeof(swMemoryPool);
pool->object = object;
pool->destroy = swRingBuffer_destory;
pool->free = swRingBuffer_free;
pool->alloc = swRingBuffer_alloc;
object->memory = mem;
swDebug("memory: ptr=%p", mem);
return pool;
}
static void swRingBuffer_collect(swRingBuffer *object)
{
swRingBuffer_item *item;
sw_atomic_t *free_count = &object->free_count;
int count = object->free_count;
int i;
uint32_t n_size;
for (i = 0; i < count; i++)
{
item = object->memory + object->collect_offset;
if (item->lock == 0)
{
n_size = item->length + sizeof(swRingBuffer_item);
object->collect_offset += n_size;
if (object->collect_offset + sizeof(swRingBuffer_item) >object->size || object->collect_offset >= object->size)
{
object->collect_offset = 0;
object->status = 0;
}
sw_atomic_fetch_sub(free_count, 1);
}
else
{
break;
}
}
}
static void* swRingBuffer_alloc(swMemoryPool *pool, uint32_t size)
{
assert(size > 0);
swRingBuffer *object = pool->object;
swRingBuffer_item *item;
uint32_t capacity;
uint32_t alloc_size = size + sizeof(swRingBuffer_item);
if (object->free_count > 0)
{
swRingBuffer_collect(object);
}
if (object->status == 0)
{
if (object->alloc_offset + alloc_size >= (object->size - sizeof(swRingBuffer_item)))
{
uint32_t skip_n = object->size - object->alloc_offset;
if (skip_n >= sizeof(swRingBuffer_item))
{
item = object->memory + object->alloc_offset;
item->lock = 0;
item->length = skip_n - sizeof(swRingBuffer_item);
sw_atomic_t *free_count = &object->free_count;
sw_atomic_fetch_add(free_count, 1);
}
object->alloc_offset = 0;
object->status = 1;
capacity = object->collect_offset - object->alloc_offset;
}
else
{
capacity = object->size - object->alloc_offset;
}
}
else
{
capacity = object->collect_offset - object->alloc_offset;
}
if (capacity < alloc_size)
{
return NULL;
}
item = object->memory + object->alloc_offset;
item->lock = 1;
item->length = size;
item->index = object->alloc_count;
object->alloc_offset += alloc_size;
object->alloc_count ++;
swDebug("alloc: ptr=%p", (void * )((void * )item->data - object->memory));
return item->data;
}
static void swRingBuffer_free(swMemoryPool *pool, void *ptr)
{
swRingBuffer *object = pool->object;
swRingBuffer_item *item = ptr - sizeof(swRingBuffer_item);
assert(ptr >= object->memory);
assert(ptr <= object->memory + object->size);
assert(item->lock == 1);
if (item->lock != 1)
{
swDebug("invalid free: index=%d, ptr=%p", item->index, (void * )((void * )item->data - object->memory));
}
else
{
item->lock = 0;
}
swDebug("free: ptr=%p", (void * )((void * )item->data - object->memory));
sw_atomic_t *free_count = &object->free_count;
sw_atomic_fetch_add(free_count, 1);
}
static void swRingBuffer_destory(swMemoryPool *pool)
{
swRingBuffer *object = pool->object;
if (object->shared)
{
sw_shm_free(object);
}
else
{
sw_free(object);
}
}

178
vendor/swoole/src/memory/ShareMemory.c vendored Executable file
View File

@@ -0,0 +1,178 @@
/*
+----------------------------------------------------------------------+
| Swoole |
+----------------------------------------------------------------------+
| This source file is subject to version 2.0 of the Apache 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.apache.org/licenses/LICENSE-2.0.html |
| If you did not receive a copy of the Apache2.0 license and are unable|
| to obtain it through the world-wide-web, please send a note to |
| license@swoole.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
+----------------------------------------------------------------------+
*/
#include "swoole.h"
#include <sys/shm.h>
void* sw_shm_malloc(size_t size)
{
swShareMemory object;
void *mem;
size += sizeof(swShareMemory);
mem = swShareMemory_mmap_create(&object, size, NULL);
if (mem == NULL)
{
return NULL;
}
else
{
memcpy(mem, &object, sizeof(swShareMemory));
return mem + sizeof(swShareMemory);
}
}
void* sw_shm_calloc(size_t num, size_t _size)
{
swShareMemory object;
void *mem;
void *ret_mem;
int size = sizeof(swShareMemory) + (num * _size);
mem = swShareMemory_mmap_create(&object, size, NULL);
if (mem == NULL)
{
return NULL;
}
else
{
memcpy(mem, &object, sizeof(swShareMemory));
ret_mem = mem + sizeof(swShareMemory);
bzero(ret_mem, size - sizeof(swShareMemory));
return ret_mem;
}
}
int sw_shm_protect(void *addr, int flags)
{
swShareMemory *object = (swShareMemory *) (addr - sizeof(swShareMemory));
return mprotect(object, object->size, flags);
}
void sw_shm_free(void *ptr)
{
swShareMemory *object = ptr - sizeof(swShareMemory);
swShareMemory_mmap_free(object);
}
void* sw_shm_realloc(void *ptr, size_t new_size)
{
swShareMemory *object = ptr - sizeof(swShareMemory);
void *new_ptr;
new_ptr = sw_shm_malloc(new_size);
if (new_ptr == NULL)
{
return NULL;
}
else
{
memcpy(new_ptr, ptr, object->size);
sw_shm_free(ptr);
return new_ptr;
}
}
void *swShareMemory_mmap_create(swShareMemory *object, size_t size, char *mapfile)
{
void *mem;
int tmpfd = -1;
int flag = MAP_SHARED;
bzero(object, sizeof(swShareMemory));
#ifdef MAP_ANONYMOUS
flag |= MAP_ANONYMOUS;
#else
if (mapfile == NULL)
{
mapfile = "/dev/zero";
}
if ((tmpfd = open(mapfile, O_RDWR)) < 0)
{
return NULL;
}
strncpy(object->mapfile, mapfile, SW_SHM_MMAP_FILE_LEN);
object->tmpfd = tmpfd;
#endif
#if defined(SW_USE_HUGEPAGE) && defined(MAP_HUGETLB)
if (size > 2 * 1024 * 1024)
{
flag |= MAP_HUGETLB;
}
#endif
mem = mmap(NULL, size, PROT_READ | PROT_WRITE, flag, tmpfd, 0);
#ifdef MAP_FAILED
if (mem == MAP_FAILED)
#else
if (!mem)
#endif
{
swWarn("mmap(%ld) failed. Error: %s[%d]", size, strerror(errno), errno);
return NULL;
}
else
{
object->size = size;
object->mem = mem;
return mem;
}
}
int swShareMemory_mmap_free(swShareMemory *object)
{
return munmap(object->mem, object->size);
}
void *swShareMemory_sysv_create(swShareMemory *object, size_t size, int key)
{
int shmid;
void *mem;
bzero(object, sizeof(swShareMemory));
if (key == 0)
{
key = IPC_PRIVATE;
}
//SHM_R | SHM_W
if ((shmid = shmget(key, size, IPC_CREAT)) < 0)
{
swSysError("shmget(%d, %ld) failed.", key, size);
return NULL;
}
if ((mem = shmat(shmid, NULL, 0)) == (void *) -1)
{
swWarn("shmat() failed. Error: %s[%d]", strerror(errno), errno);
return NULL;
}
else
{
object->key = key;
object->shmid = shmid;
object->size = size;
object->mem = mem;
return mem;
}
}
int swShareMemory_sysv_free(swShareMemory *object, int rm)
{
int shmid = object->shmid;
int ret = shmdt(object->mem);
if (rm == 1)
{
shmctl(shmid, IPC_RMID, NULL);
}
return ret;
}

483
vendor/swoole/src/memory/Table.c vendored Executable file
View File

@@ -0,0 +1,483 @@
/*
+----------------------------------------------------------------------+
| Swoole |
+----------------------------------------------------------------------+
| This source file is subject to version 2.0 of the Apache 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.apache.org/licenses/LICENSE-2.0.html |
| If you did not receive a copy of the Apache2.0 license and are unable|
| to obtain it through the world-wide-web, please send a note to |
| license@swoole.com so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Tianfeng Han <mikan.tenny@gmail.com> |
+----------------------------------------------------------------------+
*/
#include "swoole.h"
#include "table.h"
//#define SW_TABLE_DEBUG 1
#define SW_TABLE_USE_PHP_HASH
#ifdef SW_TABLE_DEBUG
static int conflict_count = 0;
static int insert_count = 0;
static int conflict_max_level = 0;
#endif
static void swTableColumn_free(swTableColumn *col);
static void swTableColumn_free(swTableColumn *col)
{
swString_free(col->name);
sw_free(col);
}
swTable* swTable_new(uint32_t rows_size, float conflict_proportion)
{
if (rows_size >= 0x80000000)
{
rows_size = 0x80000000;
}
else
{
uint32_t i = 10;
while ((1U << i) < rows_size)
{
i++;
}
rows_size = 1 << i;
}
if (conflict_proportion > 1.0)
{
conflict_proportion = 1.0;
}
else if (conflict_proportion < SW_TABLE_CONFLICT_PROPORTION)
{
conflict_proportion = SW_TABLE_CONFLICT_PROPORTION;
}
swTable *table = SwooleG.memory_pool->alloc(SwooleG.memory_pool, sizeof(swTable));
if (table == NULL)
{
return NULL;
}
if (swMutex_create(&table->lock, 1) < 0)
{
swWarn("mutex create failed.");
return NULL;
}
table->iterator = sw_malloc(sizeof(swTable_iterator));
if (!table->iterator)
{
swWarn("malloc failed.");
return NULL;
}
table->columns = swHashMap_new(SW_HASHMAP_INIT_BUCKET_N, (swHashMap_dtor)swTableColumn_free);
if (!table->columns)
{
return NULL;
}
table->size = rows_size;
table->mask = rows_size - 1;
table->conflict_proportion = conflict_proportion;
bzero(table->iterator, sizeof(swTable_iterator));
table->memory = NULL;
return table;
}
int swTableColumn_add(swTable *table, char *name, int len, int type, int size)
{
swTableColumn *col = sw_malloc(sizeof(swTableColumn));
if (!col)
{
return SW_ERR;
}
col->name = swString_dup(name, len);
if (!col->name)
{
sw_free(col);
return SW_ERR;
}
switch(type)
{
case SW_TABLE_INT:
switch(size)
{
case 1:
col->size = 1;
col->type = SW_TABLE_INT8;
break;
case 2:
col->size = 2;
col->type = SW_TABLE_INT16;
break;
#ifdef __x86_64__
case 8:
col->size = 8;
col->type = SW_TABLE_INT64;
break;
#endif
default:
col->size = 4;
col->type = SW_TABLE_INT32;
break;
}
break;
case SW_TABLE_FLOAT:
col->size = sizeof(double);
col->type = SW_TABLE_FLOAT;
break;
case SW_TABLE_STRING:
col->size = size + sizeof(swTable_string_length_t);
col->type = SW_TABLE_STRING;
break;
default:
swWarn("unkown column type.");
swTableColumn_free(col);
return SW_ERR;
}
col->index = table->item_size;
table->item_size += col->size;
table->column_num ++;
return swHashMap_add(table->columns, name, len, col);
}
size_t swTable_get_memory_size(swTable *table)
{
/**
* table size + conflict size
*/
size_t row_num = table->size * (1 + table->conflict_proportion);
/*
* header + data
*/
size_t row_memory_size = sizeof(swTableRow) + table->item_size;
/**
* row data & header
*/
size_t memory_size = row_num * row_memory_size;
/**
* memory pool for conflict rows
*/
memory_size += sizeof(swMemoryPool) + sizeof(swFixedPool) + ((row_num - table->size) * sizeof(swFixedPool_slice));
/**
* for iterator, Iterate through all the elements
*/
memory_size += table->size * sizeof(swTableRow *);
return memory_size;
}
int swTable_create(swTable *table)
{
size_t memory_size = swTable_get_memory_size(table);
size_t row_memory_size = sizeof(swTableRow) + table->item_size;
void *memory = sw_shm_malloc(memory_size);
if (memory == NULL)
{
return SW_ERR;
}
table->memory_size = memory_size;
table->memory = memory;
table->rows = memory;
memory += table->size * sizeof(swTableRow *);
memory_size -= table->size * sizeof(swTableRow *);
#if SW_TABLE_USE_SPINLOCK == 0
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
pthread_mutexattr_setrobust_np(&attr, PTHREAD_MUTEX_ROBUST_NP);
#endif
int i;
for (i = 0; i < table->size; i++)
{
table->rows[i] = memory + (row_memory_size * i);
memset(table->rows[i], 0, sizeof(swTableRow));
#if SW_TABLE_USE_SPINLOCK == 0
pthread_mutex_init(&table->rows[i]->lock, &attr);
#endif
}
memory += row_memory_size * table->size;
memory_size -= row_memory_size * table->size;
table->pool = swFixedPool_new2(row_memory_size, memory, memory_size);
return SW_OK;
}
void swTable_free(swTable *table)
{
#ifdef SW_TABLE_DEBUG
printf("swoole_table: size=%d, conflict_count=%d, conflict_max_level=%d, insert_count=%d\n", table->size,
conflict_count, conflict_max_level, insert_count);
#endif
swHashMap_free(table->columns);
sw_free(table->iterator);
if (table->memory)
{
sw_shm_free(table->memory);
}
}
static sw_inline swTableRow* swTable_hash(swTable *table, char *key, int keylen)
{
#ifdef SW_TABLE_USE_PHP_HASH
uint64_t hashv = swoole_hash_php(key, keylen);
#else
uint64_t hashv = swoole_hash_austin(key, keylen);
#endif
uint64_t index = hashv & table->mask;
assert(index < table->size);
return table->rows[index];
}
void swTable_iterator_rewind(swTable *table)
{
bzero(table->iterator, sizeof(swTable_iterator));
}
static sw_inline swTableRow* swTable_iterator_get(swTable *table, uint32_t index)
{
swTableRow *row = table->rows[index];
return row->active ? row : NULL;
}
swTableRow* swTable_iterator_current(swTable *table)
{
return table->iterator->row;
}
void swTable_iterator_forward(swTable *table)
{
for (; table->iterator->absolute_index < table->size; table->iterator->absolute_index++)
{
swTableRow *row = swTable_iterator_get(table, table->iterator->absolute_index);
if (row == NULL)
{
continue;
}
else if (row->next == NULL)
{
table->iterator->absolute_index++;
table->iterator->row = row;
return;
}
else
{
int i = 0;
for (;; i++)
{
if (row == NULL)
{
table->iterator->collision_index = 0;
break;
}
if (i == table->iterator->collision_index)
{
table->iterator->collision_index++;
table->iterator->row = row;
return;
}
row = row->next;
}
}
}
table->iterator->row = NULL;
}
swTableRow* swTableRow_get(swTable *table, char *key, int keylen, swTableRow** rowlock)
{
if (keylen > SW_TABLE_KEY_SIZE)
{
keylen = SW_TABLE_KEY_SIZE;
}
swTableRow *row = swTable_hash(table, key, keylen);
*rowlock = row;
swTableRow_lock(row);
for (;;)
{
if (strncmp(row->key, key, keylen) == 0)
{
if (!row->active)
{
row = NULL;
}
break;
}
else if (row->next == NULL)
{
row = NULL;
break;
}
else
{
row = row->next;
}
}
return row;
}
swTableRow* swTableRow_set(swTable *table, char *key, int keylen, swTableRow **rowlock)
{
if (keylen > SW_TABLE_KEY_SIZE)
{
keylen = SW_TABLE_KEY_SIZE;
}
swTableRow *row = swTable_hash(table, key, keylen);
*rowlock = row;
swTableRow_lock(row);
#ifdef SW_TABLE_DEBUG
int _conflict_level = 0;
#endif
if (row->active)
{
for (;;)
{
if (strncmp(row->key, key, keylen) == 0)
{
break;
}
else if (row->next == NULL)
{
table->lock.lock(&table->lock);
swTableRow *new_row = table->pool->alloc(table->pool, 0);
#ifdef SW_TABLE_DEBUG
conflict_count ++;
if (_conflict_level > conflict_max_level)
{
conflict_max_level = _conflict_level;
}
#endif
table->lock.unlock(&table->lock);
if (!new_row)
{
return NULL;
}
//add row_num
bzero(new_row, sizeof(swTableRow));
sw_atomic_fetch_add(&(table->row_num), 1);
row->next = new_row;
row = new_row;
break;
}
else
{
row = row->next;
#ifdef SW_TABLE_DEBUG
_conflict_level++;
#endif
}
}
}
else
{
#ifdef SW_TABLE_DEBUG
insert_count ++;
#endif
sw_atomic_fetch_add(&(table->row_num), 1);
}
memcpy(row->key, key, keylen);
row->active = 1;
return row;
}
int swTableRow_del(swTable *table, char *key, int keylen)
{
if (keylen > SW_TABLE_KEY_SIZE)
{
keylen = SW_TABLE_KEY_SIZE;
}
swTableRow *row = swTable_hash(table, key, keylen);
//no exists
if (!row->active)
{
return SW_ERR;
}
swTableRow_lock(row);
if (row->next == NULL)
{
if (strncmp(row->key, key, keylen) == 0)
{
bzero(row, sizeof(swTableRow) + table->item_size);
goto delete_element;
}
else
{
goto not_exists;
}
}
else
{
swTableRow *tmp = row;
swTableRow *prev = NULL;
while (tmp)
{
if ((strncmp(tmp->key, key, keylen) == 0))
{
break;
}
prev = tmp;
tmp = tmp->next;
}
if (tmp == NULL)
{
not_exists:
swTableRow_unlock(row);
return SW_ERR;
}
//when the deleting element is root, we should move the first element's data to root,
//and remove the element from the collision list.
if (tmp == row)
{
tmp = tmp->next;
row->next = tmp->next;
memcpy(row->key, tmp->key, strlen(tmp->key));
memcpy(row->data, tmp->data, table->item_size);
}
if (prev)
{
prev->next = tmp->next;
}
table->lock.lock(&table->lock);
bzero(tmp, sizeof(swTableRow) + table->item_size);
table->pool->free(table->pool, tmp);
table->lock.unlock(&table->lock);
}
delete_element:
sw_atomic_fetch_sub(&(table->row_num), 1);
swTableRow_unlock(row);
return SW_OK;
}