Preview: swoole_table.h
Size: 6.50 KB
/proc/thread-self/root/proc/self/root/opt/alt/php83/usr/include/php/ext/swoole/include/swoole_table.h
/*
+----------------------------------------------------------------------+
| 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 <rango@swoole.com> |
+----------------------------------------------------------------------+
*/
#pragma once
#include "swoole_memory.h"
#include "swoole_lock.h"
#include <csignal>
#include <vector>
#include <unordered_map>
//#define SW_TABLE_DEBUG 0
#define SW_TABLE_FORCE_UNLOCK_TIME 2000 // milliseconds
#define SW_TABLE_USE_PHP_HASH
#define SW_TABLE_MAX_ROW_SIZE 0x80000000
namespace swoole {
typedef uint32_t TableStringLength;
typedef uint64_t (*HashFunc)(const char *key, size_t len);
struct TableColumn;
struct TableRow {
sw_atomic_t lock_;
pid_t lock_pid;
/**
* 1:used, 0:empty
*/
uint8_t active;
uint8_t key_len;
/**
* next slot
*/
TableRow *next;
/**
* Hash Key
*/
char key[SW_TABLE_KEY_SIZE];
char data[0];
void lock();
void unlock() {
sw_spinlock_release(&lock_);
}
void clear() {
sw_memset_zero((char *) &lock_pid, sizeof(TableRow) - offsetof(TableRow, lock_pid));
}
void set_value(const TableColumn *col, const void *value, size_t vlen);
void get_value(const TableColumn *col, double *dval) const;
void get_value(const TableColumn *col, long *lval) const;
void get_value(const TableColumn *col, char **strval, TableStringLength *strlen);
};
struct TableIterator {
size_t row_memory_size_;
uint32_t absolute_index = 0;
uint32_t collision_index = 0;
TableRow *current_;
Mutex *mutex_;
explicit TableIterator(size_t row_size);
~TableIterator();
void reset();
void lock() const {
mutex_->lock();
}
void unlock() const {
mutex_->unlock();
}
};
enum TableFlag {
SW_TABLE_FLAG_NEW_ROW = 1,
SW_TABLE_FLAG_CONFLICT = 1u << 1,
};
struct TableColumn {
enum Type {
TYPE_INT = 1,
TYPE_FLOAT,
TYPE_STRING,
};
Type type;
uint32_t size;
std::string name;
size_t index;
TableColumn(const std::string &_name, Type _type, size_t _size);
void clear(TableRow *row) const;
};
class Table {
std::unordered_map<std::string, TableColumn *> *column_map;
Mutex *mutex;
size_t size;
size_t mask;
size_t item_size;
size_t memory_size;
float conflict_proportion;
/**
* total rows that in active state(shm)
*/
sw_atomic_t row_num;
TableRow **rows;
FixedPool *pool;
TableIterator *iterator;
HashFunc hash_func;
bool created;
void *memory;
public:
std::vector<TableColumn *> *column_list;
size_t conflict_count;
sw_atomic_long_t insert_count;
sw_atomic_long_t delete_count;
sw_atomic_long_t update_count;
uint32_t conflict_max_level;
Table() = delete;
~Table() = delete;
static Table *make(uint32_t rows_size, float conflict_proportion);
size_t calc_memory_size() const;
size_t get_memory_size() const;
uint32_t get_available_slice_num() const;
uint32_t get_total_slice_num() const;
bool create();
bool add_column(const std::string &name, enum TableColumn::Type type, size_t size);
TableColumn *get_column(const std::string &key) const;
TableRow *set(const char *key, uint16_t keylen, TableRow **rowlock, int *out_flags);
TableRow *get(const char *key, uint16_t keylen, TableRow **rowlock) const;
bool exists(const char *key, uint16_t keylen) const;
bool del(const char *key, uint16_t keylen);
void forward() const;
// release shared memory
void destroy();
bool is_created() const {
return created;
}
bool ready() const {
return memory != nullptr;
}
void set_hash_func(HashFunc _fn) {
hash_func = _fn;
}
size_t get_size() const {
return size;
}
float get_conflict_proportion() const {
return conflict_proportion;
}
size_t get_column_size() const {
return column_map->size();
}
TableRow *get_by_index(uint32_t index) const {
TableRow *row = rows[index];
return row->active ? row : nullptr;
}
size_t count() const {
return row_num;
}
bool exists(const std::string &key) const {
return exists(key.c_str(), key.length());
}
TableRow *current() const {
return iterator->current_;
}
void rewind() const {
iterator->lock();
iterator->reset();
iterator->unlock();
}
void clear_row(TableRow *row) const {
for (auto &i : *column_list) {
i->clear(row);
}
}
private:
TableRow *hash(const char *key, int keylen) const {
uint64_t hashv = hash_func(key, keylen);
uint64_t index = hashv & mask;
assert(index < size);
return rows[index];
}
TableRow *alloc_row() const {
lock();
const auto new_row = static_cast<TableRow *>(pool->alloc(0));
unlock();
return new_row;
}
void free_row(TableRow *tmp) const {
lock();
tmp->clear();
pool->free(tmp);
unlock();
}
static void check_key_length(uint16_t *keylen) {
if (*keylen >= SW_TABLE_KEY_SIZE) {
*keylen = SW_TABLE_KEY_SIZE - 1;
}
}
void init_row(TableRow *new_row, const char *key, int keylen) {
sw_memset_zero(reinterpret_cast<char *>(new_row) + offsetof(TableRow, active),
sizeof(TableRow) - offsetof(TableRow, active));
memcpy(new_row->key, key, keylen);
new_row->key[keylen] = '\0';
new_row->key_len = keylen;
new_row->active = 1;
sw_atomic_fetch_add(&(row_num), 1);
}
int lock() const {
return mutex->lock();
}
int unlock() const {
return mutex->unlock();
}
};
} // namespace swoole
Directory Contents
Dirs: 0 × Files: 55