swTableRow* swTableRow_get(swTable *table, char *key, int keylen, sw_atomic_t **rowlock) { if (keylen > SW_TABLE_KEY_SIZE) { keylen = SW_TABLE_KEY_SIZE; } swTableRow *row = swTable_hash(table, key, keylen); sw_atomic_t *lock = &row->lock; sw_spinlock(lock); *rowlock = lock; 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_get(swTable *table, char *key, int keylen) { swTableRow *row = swTable_hash(table, key, keylen); uint32_t crc32 = swoole_crc32(key, keylen); sw_atomic_t *lock = &row->lock; swTrace("row=%p, crc32=%u, key=%s\n", row, crc32, key); sw_spinlock(lock); for (;;) { if (row->crc32 == crc32) { if (!row->active) { row = NULL; } break; } else if (row->next == NULL) { row = NULL; break; } else { row = row->next; } } sw_spinlock_release(lock); return row; }
swTableRow* swTableRow_get(swTable *table, char *key, int keylen) { swTableRow *row = swTable_hash(table, key, keylen); if (keylen > SW_TABLE_KEY_SIZE) { keylen = SW_TABLE_KEY_SIZE; } sw_atomic_t *lock = &row->lock; swTrace("row=%p, crc32=%u, key=%s\n", row, crc32, key); sw_spinlock(lock); 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; } } sw_spinlock_release(lock); return row; }
static PHP_METHOD(swoole_table, set) { zval *array; char *key; zend_size_t keylen; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa", &key, &keylen, &array) == FAILURE) { RETURN_FALSE; } swTable *table = swoole_get_object(getThis()); swTableRow *row = swTableRow_set(table, key, keylen); if (!row) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to allocate memory."); RETURN_FALSE; } swTableColumn *col; zval *v; char *k; uint32_t klen; int ktype; HashTable *_ht = Z_ARRVAL_P(array); sw_atomic_t *lock = &row->lock; sw_spinlock(lock); SW_HASHTABLE_FOREACH_START2(_ht, k, klen, ktype, v) { //printf("key=%s, klen=%d, ktype=%d\n", k, klen, ktype); col = swTableColumn_get(table, k, klen); if (k == NULL || col == NULL) { continue; } else if (col->type == SW_TABLE_STRING) { convert_to_string(v); swTableRow_set_value(row, col, Z_STRVAL_P(v), Z_STRLEN_P(v)); } else if (col->type == SW_TABLE_FLOAT) { convert_to_double(v); swTableRow_set_value(row, col, &Z_DVAL_P(v), 0); } else { convert_to_long(v); swTableRow_set_value(row, col, &Z_LVAL_P(v), 0); } }
static void php_swoole_table_row2array(swTable *table, swTableRow *row, zval *return_value) { array_init(return_value); swTableColumn *col = NULL; swTable_string_length_t vlen = 0; double dval = 0; int64_t lval = 0; char *k; sw_spinlock(&row->lock); while(1) { col = swHashMap_each(table->columns, &k); if (col == NULL) { break; } if (col->type == SW_TABLE_STRING) { memcpy(&vlen, row->data + col->index, sizeof(swTable_string_length_t)); sw_add_assoc_stringl_ex(return_value, col->name->str, col->name->length + 1, row->data + col->index + sizeof(swTable_string_length_t), vlen, 1); } else if (col->type == SW_TABLE_FLOAT) { memcpy(&dval, row->data + col->index, sizeof(dval)); sw_add_assoc_double_ex(return_value, col->name->str, col->name->length + 1, dval); } else { switch (col->type) { case SW_TABLE_INT8: memcpy(&lval, row->data + col->index, 1); sw_add_assoc_long_ex(return_value, col->name->str, col->name->length + 1, (int8_t) lval); break; case SW_TABLE_INT16: memcpy(&lval, row->data + col->index, 2); sw_add_assoc_long_ex(return_value, col->name->str, col->name->length + 1, (int16_t) lval); break; case SW_TABLE_INT32: memcpy(&lval, row->data + col->index, 4); sw_add_assoc_long_ex(return_value, col->name->str, col->name->length + 1, (int32_t) lval); break; default: memcpy(&lval, row->data + col->index, 8); sw_add_assoc_long_ex(return_value, col->name->str, col->name->length + 1, lval); break; } } } sw_spinlock_release(&row->lock); }
int swTableRow_del(swTable *table, char *key, int keylen) { swTableRow *row = swTable_hash(table, key, keylen); uint32_t crc32 = swoole_crc32(key, keylen); sw_atomic_t *lock = &row->lock; //no exists if (!row->active) { return SW_ERR; } sw_spinlock(lock); if (row->next == NULL) { if (row->crc32 == crc32) { table->rows_list[row->list_index] = NULL; if (table->iterator->skip_count > table->compress_threshold) { swTable_compress_list(table); } bzero(row, sizeof(swTableRow)); goto delete_element; } else { goto not_exists; } } else { swTableRow *tmp = row; swTableRow *prev = NULL; while (tmp) { if (tmp->crc32 == crc32) { break; } prev = tmp; tmp = tmp->next; } if (tmp == NULL) { not_exists: sw_spinlock_release(lock); 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; if (table->iterator->skip_count > table->compress_threshold) { swTable_compress_list(table); } memcpy(row->data, tmp->data, table->item_size); } if (prev) { prev->next = tmp->next; } table->lock.lock(&table->lock); bzero(tmp, sizeof(swTableRow)); table->pool->free(table->pool, tmp); table->lock.unlock(&table->lock); } delete_element: sw_atomic_fetch_sub(&(table->row_num), 1); sw_spinlock_release(lock); return SW_OK; }
swTableRow* swTableRow_set(swTable *table, char *key, int keylen) { swTableRow *row = swTable_hash(table, key, keylen); uint32_t crc32 = swoole_crc32(key, keylen); sw_atomic_t *lock = &row->lock; sw_spinlock(lock); if (row->active) { for (;;) { if (row->crc32 == crc32) { 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 ++; #endif table->lock.unlock(&table->lock); if (!new_row) { sw_spinlock_release(lock); 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; } } } else { #ifdef SW_TABLE_DEBUG insert_count ++; #endif sw_atomic_fetch_add(&(table->row_num), 1); // when the root node become active, we may need compress the jump table if (table->list_n >= table->size - 1) { swTable_compress_list(table); } table->rows_list[table->list_n] = row; row->list_index = table->list_n; sw_atomic_fetch_add(&table->list_n, 1); } row->crc32 = crc32; row->active = 1; swTrace("row=%p, crc32=%u, key=%s\n", row, crc32, key); sw_spinlock_release(lock); return row; }
static int swAtomicLock_lock(swLock *lock) { sw_spinlock(&lock->object.atomlock.lock_t); return SW_OK; }
swTableRow* swTableRow_set(swTable *table, char *key, int keylen, sw_atomic_t **rowlock) { if (keylen > SW_TABLE_KEY_SIZE) { keylen = SW_TABLE_KEY_SIZE; } swTableRow *row = swTable_hash(table, key, keylen); sw_atomic_t *lock = &row->lock; sw_spinlock(lock); *rowlock = lock; 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 ++; #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; } } } else { #ifdef SW_TABLE_DEBUG insert_count ++; #endif sw_atomic_fetch_add(&(table->row_num), 1); // when the root node become active, we may need compress the jump table if (table->list_n >= table->size - 1) { swTable_compress_list(table); } table->lock.lock(&table->lock); table->rows_list[table->list_n] = row; table->lock.unlock(&table->lock); row->list_index = table->list_n; sw_atomic_fetch_add(&table->list_n, 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); sw_atomic_t *lock = &row->lock; //no exists if (!row->active) { return SW_ERR; } sw_spinlock(lock); 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: sw_spinlock_release(lock); 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); sw_spinlock_release(lock); return SW_OK; }
swTableRow* swTableRow_set(swTable *table, char *key, int keylen, sw_atomic_t **rowlock) { if (keylen > SW_TABLE_KEY_SIZE) { keylen = SW_TABLE_KEY_SIZE; } swTableRow *row = swTable_hash(table, key, keylen); sw_atomic_t *lock = &row->lock; sw_spinlock(lock); *rowlock = lock; #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) { swTableRow *row = swTable_hash(table, key, keylen); uint32_t crc32 = swoole_crc32(key, keylen); sw_atomic_t *lock = &row->lock; int i = 0; sw_spinlock(lock); if (row->active) { for (;; i++) { if (row->crc32 == crc32) { if (i > 0) { table->lock.lock(&table->lock); table->pool->free(table->pool, row); table->lock.unlock(&table->lock); } break; } else if (row->next == NULL) { sw_spinlock_release(lock); return SW_ERR; } else { row = row->next; } } #ifdef SW_TABLE_USE_LINKED_LIST if (row->list_prev != NULL) { row->list_prev->list_next = row->list_next; } else { table->head = row->list_next; } if (row->list_next != NULL) { row->list_next->list_prev = row->list_prev; } else { table->tail = row->list_prev; } if (table->iterator->tmp_row == row) { table->iterator->tmp_row = row->list_next; } #endif } if (row->active) { sw_atomic_fetch_sub(&(table->row_num), 1); } row->active = 0; sw_spinlock_release(lock); return SW_OK; }
swTableRow* swTableRow_set(swTable *table, char *key, int keylen) { swTableRow *row = swTable_hash(table, key, keylen); uint32_t crc32 = swoole_crc32(key, keylen); sw_atomic_t *lock = &row->lock; sw_spinlock(lock); if (row->active) { for (;;) { if (row->crc32 == crc32) { break; } else if (row->next == NULL) { table->lock.lock(&table->lock); swTableRow *new_row = table->pool->alloc(table->pool, 0); table->lock.unlock(&table->lock); if (!new_row) { sw_spinlock_release(lock); return NULL; } //add row_num sw_atomic_fetch_add(&(table->row_num), 1); row->next = new_row; row = new_row; break; } else { row = row->next; } } } else { sw_atomic_fetch_add(&(table->row_num), 1); } #ifdef SW_TABLE_USE_LINKED_LIST if (!row->active) { row->list_next = NULL; if (table->head) { row->list_prev = table->tail; table->tail->list_next = row; table->tail = row; } else { table->head = table->tail = row; row->list_prev = NULL; table->iterator->tmp_row = row; } } #endif row->crc32 = crc32; row->active = 1; swTrace("row=%p, crc32=%u, key=%s\n", row, crc32, key); sw_spinlock_release(lock); return row; }