add hash/kvs-client
This commit is contained in:
34
Makefile
34
Makefile
@@ -1,15 +1,33 @@
|
|||||||
|
|
||||||
|
|
||||||
CC = gcc
|
CC = gcc
|
||||||
|
FLAGS = -I ./NtyCo/core/ -L ./NtyCo/ -lntyco -lpthread -luring -ldl
|
||||||
|
SRCS = kvstore.c ntyco.c proactor.c kvs_array.c kvs_rbtree.c kvs_hash.c
|
||||||
|
TESTCASE_SRCS = testcase.c
|
||||||
TARGET = kvstore
|
TARGET = kvstore
|
||||||
SRCS = kvstore.c ntyco.c proactor.c kvs_array.c kvs_rbtree.c
|
SUBDIR = ./NtyCo/
|
||||||
INC = -I ./NtyCo/core/
|
TESTCASE = testcase
|
||||||
LIBS = -L ./NtyCo/ -lntyco -luring
|
|
||||||
|
OBJS = $(SRCS:.c=.o)
|
||||||
|
|
||||||
|
|
||||||
all:
|
all: $(SUBDIR) $(TARGET) $(TESTCASE)
|
||||||
$(CC) -o $(TARGET) $(SRCS) $(INC) $(LIBS)
|
|
||||||
|
$(SUBDIR): ECHO
|
||||||
|
make -C $@
|
||||||
|
|
||||||
|
ECHO:
|
||||||
|
@echo $(SUBDIR)
|
||||||
|
|
||||||
|
$(TARGET): $(OBJS)
|
||||||
|
$(CC) -o $@ $^ $(FLAGS)
|
||||||
|
|
||||||
|
$(TESTCASE): $(TESTCASE_SRCS)
|
||||||
|
$(CC) -o $@ $^
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
$(CC) $(FLAGS) -c $^ -o $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(OBJS) $(TARGET) $(TESTCASE)
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf kvstore
|
|
||||||
|
|
||||||
|
|||||||
29
Makefile.default
Normal file
29
Makefile.default
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
|
||||||
|
CC = gcc
|
||||||
|
FLAGS = -I ./NtyCo/core/ -L ./NtyCo/ -lntyco -luring
|
||||||
|
TARGET = kvstore
|
||||||
|
|
||||||
|
SRCS = kvstore.c ntyco.c proactor.c kvs_array.c kvs_rbtree.c
|
||||||
|
# INC = -I ./NtyCo/core/
|
||||||
|
# LIBS = -L ./NtyCo/ -lntyco -luring
|
||||||
|
# FLAGS = -I ./NtyCo/core/ -L ./NtyCo/ -lntyco -luring
|
||||||
|
|
||||||
|
OBJS = $(SRCS:.c=.o)
|
||||||
|
TESTCASE = testcase
|
||||||
|
SUBDIR = ./NtyCo/
|
||||||
|
|
||||||
|
all: $(SUBDIR) $(TARGET) # $(TESTCASE)
|
||||||
|
|
||||||
|
$(SUBDIR): ECHO
|
||||||
|
make -C $@
|
||||||
|
|
||||||
|
ECHO:
|
||||||
|
@echo $(SUBDIR)
|
||||||
|
|
||||||
|
$(TARGET): $(OBJS)
|
||||||
|
$(CC) -o $@ $^ $(FLAGS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf kvstore *.o
|
||||||
|
|
||||||
228
hash.c
Executable file
228
hash.c
Executable file
@@ -0,0 +1,228 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX_KEY_LEN 128
|
||||||
|
#define MAX_VALUE_LEN 512
|
||||||
|
#define MAX_TABLE_SIZE 1024
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct hashnode_s {
|
||||||
|
|
||||||
|
char key[MAX_KEY_LEN];
|
||||||
|
char value[MAX_VALUE_LEN];
|
||||||
|
|
||||||
|
struct hashnode_s *next;
|
||||||
|
|
||||||
|
} hashnode_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct hashtable_s {
|
||||||
|
|
||||||
|
hashnode_t **nodes; //* change **,
|
||||||
|
|
||||||
|
int max_slots;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
pthread_mutex_t lock;
|
||||||
|
|
||||||
|
} hashtable_t;
|
||||||
|
|
||||||
|
hashtable_t hash;
|
||||||
|
|
||||||
|
|
||||||
|
//Connection
|
||||||
|
// 'C' + 'o' + 'n'
|
||||||
|
static int _hash(char *key, int size) {
|
||||||
|
|
||||||
|
if (!key) return -1;
|
||||||
|
|
||||||
|
int sum = 0;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while (key[i] != 0) {
|
||||||
|
sum += key[i];
|
||||||
|
i ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum % size;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
hashnode_t *_create_node(char *key, char *value) {
|
||||||
|
|
||||||
|
hashnode_t *node = (hashnode_t*)malloc(sizeof(hashnode_t));
|
||||||
|
if (!node) return NULL;
|
||||||
|
|
||||||
|
strncpy(node->key, key, MAX_KEY_LEN);
|
||||||
|
strncpy(node->value, value, MAX_VALUE_LEN);
|
||||||
|
node->next = NULL;
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
int init_hashtable(hashtable_t *hash) {
|
||||||
|
|
||||||
|
if (!hash) return -1;
|
||||||
|
|
||||||
|
hash->nodes = (hashnode_t**)malloc(sizeof(hashnode_t*) * MAX_TABLE_SIZE);
|
||||||
|
if (!hash->nodes) return -1;
|
||||||
|
|
||||||
|
hash->max_slots = MAX_TABLE_SIZE;
|
||||||
|
hash->count = 0;
|
||||||
|
|
||||||
|
pthread_mutex_init(&hash->lock, NULL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
void dest_hashtable(hashtable_t *hash) {
|
||||||
|
|
||||||
|
if (!hash) return;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (i = 0;i < hash->max_slots;i ++) {
|
||||||
|
hashnode_t *node = hash->nodes[i];
|
||||||
|
|
||||||
|
while (node != NULL) { // error
|
||||||
|
|
||||||
|
hashnode_t *tmp = node;
|
||||||
|
node = node->next;
|
||||||
|
hash->nodes[i] = node;
|
||||||
|
|
||||||
|
free(tmp);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(hash->nodes);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// mp
|
||||||
|
int put_kv_hashtable(hashtable_t *hash, char *key, char *value) {
|
||||||
|
|
||||||
|
if (!hash || !key || !value) return -1;
|
||||||
|
|
||||||
|
int idx = _hash(key, MAX_TABLE_SIZE);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&hash->lock);
|
||||||
|
|
||||||
|
hashnode_t *node = hash->nodes[idx];
|
||||||
|
#if 1
|
||||||
|
while (node != NULL) {
|
||||||
|
if (strcmp(node->key, key) == 0) { // exist
|
||||||
|
pthread_mutex_unlock(&hash->lock);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
hashnode_t *new_node = _create_node(key, value);
|
||||||
|
new_node->next = hash->nodes[idx];
|
||||||
|
hash->nodes[idx] = new_node;
|
||||||
|
|
||||||
|
hash->count ++;
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&hash->lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char * get_kv_hashtable(hashtable_t *hash, char *key) {
|
||||||
|
|
||||||
|
if (!hash || !key) return NULL;
|
||||||
|
|
||||||
|
int idx = _hash(key, MAX_TABLE_SIZE);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&hash->lock);
|
||||||
|
hashnode_t *node = hash->nodes[idx];
|
||||||
|
|
||||||
|
while (node != NULL) {
|
||||||
|
|
||||||
|
if (strcmp(node->key, key) == 0) {
|
||||||
|
pthread_mutex_unlock(&hash->lock);
|
||||||
|
return node->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&hash->lock);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int count_kv_hashtable(hashtable_t *hash) {
|
||||||
|
return hash->count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int delete_kv_hashtable(hashtable_t *hash, char *key) {
|
||||||
|
if (!hash || !key) return -2;
|
||||||
|
|
||||||
|
int idx = _hash(key, MAX_TABLE_SIZE);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&hash->lock);
|
||||||
|
hashnode_t *head = hash->nodes[idx];
|
||||||
|
if (head == NULL) return -1; // noexist
|
||||||
|
// head node
|
||||||
|
if (strcmp(head->key, key) == 0) {
|
||||||
|
hashnode_t *tmp = head->next;
|
||||||
|
hash->nodes[idx] = tmp;
|
||||||
|
|
||||||
|
free(head);
|
||||||
|
hash->count --;
|
||||||
|
pthread_mutex_unlock(&hash->lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hashnode_t *cur = head;
|
||||||
|
while (cur->next != NULL) {
|
||||||
|
if (strcmp(cur->next->key, key) == 0) break; // search node
|
||||||
|
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur->next == NULL) {
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&hash->lock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
hashnode_t *tmp = cur->next;
|
||||||
|
cur->next = tmp->next;
|
||||||
|
free(tmp);
|
||||||
|
hash->count --;
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&hash->lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int exist_kv_hashtable(hashtable_t *hash, char *key) {
|
||||||
|
|
||||||
|
char *value = get_kv_hashtable(hash, key);
|
||||||
|
if (value) return 1;
|
||||||
|
else return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
42
kvs-client/go-kvstore.go
Executable file
42
kvs-client/go-kvstore.go
Executable file
@@ -0,0 +1,42 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
conn, err := net.Dial("tcp", "192.168.243.131:2000")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("connect failed: ", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
message := "SET Teacher King"
|
||||||
|
_, err = conn.Write([]byte(message))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("send failed: ", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("send msg: %s\n", message)
|
||||||
|
|
||||||
|
buffer := make([]byte, 1024)
|
||||||
|
length, err := conn.Read(buffer)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("recv failed: ", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
response := string(buffer[:length])
|
||||||
|
fmt.Printf("recv msg: %s\n", response)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
37
kvs-client/javakvstore.java
Executable file
37
kvs-client/javakvstore.java
Executable file
@@ -0,0 +1,37 @@
|
|||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.*;
|
||||||
|
|
||||||
|
public class javakvstore {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
String serverAddress = "192.168.243.131";
|
||||||
|
int serverPort = 2000;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Socket socket = new Socket(serverAddress, serverPort);
|
||||||
|
|
||||||
|
OutputStream outputStream = socket.getOutputStream();
|
||||||
|
InputStream inputStream = socket.getInputStream();
|
||||||
|
|
||||||
|
String message = "SET T1 KING";
|
||||||
|
outputStream.write(message.getBytes());
|
||||||
|
|
||||||
|
byte[] buffer = new byte[1024];
|
||||||
|
int bytesRead = inputStream.read(buffer);
|
||||||
|
if (bytesRead > 0) {
|
||||||
|
String response = new String(buffer, 0, bytesRead);
|
||||||
|
System.out.println("recv: " + response);
|
||||||
|
}
|
||||||
|
|
||||||
|
inputStream.close();
|
||||||
|
outputStream.close();
|
||||||
|
socket.close();
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
26
kvs-client/js-kvstore.js
Executable file
26
kvs-client/js-kvstore.js
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
|
||||||
|
const net = require('net');
|
||||||
|
|
||||||
|
const client = net.createConnection({ port: 2000, host: '192.168.243.131' }, () => {
|
||||||
|
console.log('connect kvstore');
|
||||||
|
|
||||||
|
client.write('GET Teacher');
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('data', (data) => {
|
||||||
|
console.log(`recv:${data.toString()}`);
|
||||||
|
|
||||||
|
client.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('error', (err) => {
|
||||||
|
console.error('connect failed:', err);
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('close', () => {
|
||||||
|
console.log('close connection');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
30
kvs-client/py-kvstore.py
Executable file
30
kvs-client/py-kvstore.py
Executable file
@@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import socket
|
||||||
|
|
||||||
|
def main():
|
||||||
|
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
|
||||||
|
server_address = ('192.168.243.131', 2000)
|
||||||
|
|
||||||
|
try:
|
||||||
|
client_socket.connect(server_address)
|
||||||
|
|
||||||
|
message = "GET Teacher"
|
||||||
|
client_socket.sendall(message.encode())
|
||||||
|
|
||||||
|
response = client_socket.recv(1024)
|
||||||
|
|
||||||
|
print("recv:", response.decode())
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print("发生异常:", str(e))
|
||||||
|
|
||||||
|
finally:
|
||||||
|
client_socket.close()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
||||||
18
kvs-client/rust-kvstore.rs
Executable file
18
kvs-client/rust-kvstore.rs
Executable file
@@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
|
||||||
|
use std::io::{self, Read, Write};
|
||||||
|
use std::net::TcpStream;
|
||||||
|
|
||||||
|
fn main() -> io::Result<()> {
|
||||||
|
let server_address = "192.168.243.131:2000";
|
||||||
|
|
||||||
|
let mut stream = TcpStream::connect(server_address)?;
|
||||||
|
|
||||||
|
stream.write_all(b"GET Teacher")?;
|
||||||
|
|
||||||
|
let mut buffer = [0; 1024];
|
||||||
|
let bytes_read = stream.read(&mut buffer)?;
|
||||||
|
println!("Received: {}", String::from_utf8_lossy(&buffer[..bytes_read]));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
12
kvs_array.c
12
kvs_array.c
@@ -118,8 +118,11 @@ int kvs_array_del(kvs_array_t *inst, char *key) {
|
|||||||
|
|
||||||
kvs_free(inst->table[i].value);
|
kvs_free(inst->table[i].value);
|
||||||
inst->table[i].value = NULL;
|
inst->table[i].value = NULL;
|
||||||
|
// error: > 1024
|
||||||
inst->idx = i;
|
if (inst->total-1 == i) {
|
||||||
|
inst->total --;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -136,6 +139,11 @@ int kvs_array_del(kvs_array_t *inst, char *key) {
|
|||||||
int kvs_array_mod(kvs_array_t *inst, char *key, char *value) {
|
int kvs_array_mod(kvs_array_t *inst, char *key, char *value) {
|
||||||
|
|
||||||
if (inst == NULL || key == NULL || value == NULL) return -1;
|
if (inst == NULL || key == NULL || value == NULL) return -1;
|
||||||
|
// error: > 1024
|
||||||
|
if (inst->total == 0) {
|
||||||
|
return KVS_ARRAY_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (i = 0;i < inst->total;i ++) {
|
for (i = 0;i < inst->total;i ++) {
|
||||||
|
|||||||
285
kvs_hash.c
Executable file
285
kvs_hash.c
Executable file
@@ -0,0 +1,285 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "kvstore.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Key, Value -->
|
||||||
|
// Modify
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
kvs_hash_t global_hash;
|
||||||
|
|
||||||
|
|
||||||
|
//Connection
|
||||||
|
// 'C' + 'o' + 'n'
|
||||||
|
static int _hash(char *key, int size) {
|
||||||
|
|
||||||
|
if (!key) return -1;
|
||||||
|
|
||||||
|
int sum = 0;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while (key[i] != 0) {
|
||||||
|
sum += key[i];
|
||||||
|
i ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sum % size;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
hashnode_t *_create_node(char *key, char *value) {
|
||||||
|
|
||||||
|
hashnode_t *node = (hashnode_t*)kvs_malloc(sizeof(hashnode_t));
|
||||||
|
if (!node) return NULL;
|
||||||
|
|
||||||
|
#if ENABLE_KEY_POINTER
|
||||||
|
char *kcopy = kvs_malloc(strlen(key) + 1);
|
||||||
|
if (kcopy == NULL) return NULL;
|
||||||
|
memset(kcopy, 0, strlen(key) + 1);
|
||||||
|
strncpy(kcopy, key, strlen(key));
|
||||||
|
|
||||||
|
node->key = kcopy;
|
||||||
|
|
||||||
|
char *kvalue = kvs_malloc(strlen(value) + 1);
|
||||||
|
if (kvalue == NULL) {
|
||||||
|
kvs_free(kvalue);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
memset(kvalue, 0, strlen(value) + 1);
|
||||||
|
strncpy(kvalue, value, strlen(value));
|
||||||
|
|
||||||
|
node->value = kvalue;
|
||||||
|
|
||||||
|
#else
|
||||||
|
strncpy(node->key, key, MAX_KEY_LEN);
|
||||||
|
strncpy(node->value, value, MAX_VALUE_LEN);
|
||||||
|
#endif
|
||||||
|
node->next = NULL;
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
int kvs_hash_create(kvs_hash_t *hash) {
|
||||||
|
|
||||||
|
if (!hash) return -1;
|
||||||
|
|
||||||
|
hash->nodes = (hashnode_t**)kvs_malloc(sizeof(hashnode_t*) * MAX_TABLE_SIZE);
|
||||||
|
if (!hash->nodes) return -1;
|
||||||
|
|
||||||
|
hash->max_slots = MAX_TABLE_SIZE;
|
||||||
|
hash->count = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
void kvs_hash_destory(kvs_hash_t *hash) {
|
||||||
|
|
||||||
|
if (!hash) return;
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (i = 0;i < hash->max_slots;i ++) {
|
||||||
|
hashnode_t *node = hash->nodes[i];
|
||||||
|
|
||||||
|
while (node != NULL) { // error
|
||||||
|
|
||||||
|
hashnode_t *tmp = node;
|
||||||
|
node = node->next;
|
||||||
|
hash->nodes[i] = node;
|
||||||
|
|
||||||
|
kvs_free(tmp);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
kvs_free(hash->nodes);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5 + 2
|
||||||
|
|
||||||
|
// mp
|
||||||
|
int kvs_hash_set(kvs_hash_t *hash, char *key, char *value) {
|
||||||
|
|
||||||
|
if (!hash || !key || !value) return -1;
|
||||||
|
|
||||||
|
int idx = _hash(key, MAX_TABLE_SIZE);
|
||||||
|
|
||||||
|
hashnode_t *node = hash->nodes[idx];
|
||||||
|
#if 1
|
||||||
|
while (node != NULL) {
|
||||||
|
if (strcmp(node->key, key) == 0) { // exist
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
hashnode_t *new_node = _create_node(key, value);
|
||||||
|
new_node->next = hash->nodes[idx];
|
||||||
|
hash->nodes[idx] = new_node;
|
||||||
|
|
||||||
|
hash->count ++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char * kvs_hash_get(kvs_hash_t *hash, char *key) {
|
||||||
|
|
||||||
|
if (!hash || !key) return NULL;
|
||||||
|
|
||||||
|
int idx = _hash(key, MAX_TABLE_SIZE);
|
||||||
|
|
||||||
|
hashnode_t *node = hash->nodes[idx];
|
||||||
|
|
||||||
|
while (node != NULL) {
|
||||||
|
|
||||||
|
if (strcmp(node->key, key) == 0) {
|
||||||
|
return node->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int kvs_hash_mod(kvs_hash_t *hash, char *key, char *value) {
|
||||||
|
|
||||||
|
if (!hash || !key) return -1;
|
||||||
|
|
||||||
|
int idx = _hash(key, MAX_TABLE_SIZE);
|
||||||
|
|
||||||
|
hashnode_t *node = hash->nodes[idx];
|
||||||
|
|
||||||
|
while (node != NULL) {
|
||||||
|
|
||||||
|
if (strcmp(node->key, key) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = node->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node == NULL) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// node -->
|
||||||
|
kvs_free(node->value);
|
||||||
|
|
||||||
|
char *kvalue = kvs_malloc(strlen(value) + 1);
|
||||||
|
if (kvalue == NULL) return -2;
|
||||||
|
memset(kvalue, 0, strlen(value) + 1);
|
||||||
|
strncpy(kvalue, value, strlen(value));
|
||||||
|
|
||||||
|
node->value = kvalue;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int kvs_hash_count(kvs_hash_t *hash) {
|
||||||
|
return hash->count;
|
||||||
|
}
|
||||||
|
|
||||||
|
int kvs_hash_del(kvs_hash_t *hash, char *key) {
|
||||||
|
if (!hash || !key) return -2;
|
||||||
|
|
||||||
|
int idx = _hash(key, MAX_TABLE_SIZE);
|
||||||
|
|
||||||
|
hashnode_t *head = hash->nodes[idx];
|
||||||
|
if (head == NULL) return -1; // noexist
|
||||||
|
// head node
|
||||||
|
if (strcmp(head->key, key) == 0) {
|
||||||
|
hashnode_t *tmp = head->next;
|
||||||
|
hash->nodes[idx] = tmp;
|
||||||
|
|
||||||
|
kvs_free(head);
|
||||||
|
hash->count --;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hashnode_t *cur = head;
|
||||||
|
while (cur->next != NULL) {
|
||||||
|
if (strcmp(cur->next->key, key) == 0) break; // search node
|
||||||
|
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur->next == NULL) {
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
hashnode_t *tmp = cur->next;
|
||||||
|
cur->next = tmp->next;
|
||||||
|
#if ENABLE_KEY_POINTER
|
||||||
|
kvs_free(tmp->key);
|
||||||
|
kvs_free(tmp->value);
|
||||||
|
#endif
|
||||||
|
kvs_free(tmp);
|
||||||
|
|
||||||
|
hash->count --;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int kvs_hash_exist(kvs_hash_t *hash, char *key) {
|
||||||
|
|
||||||
|
char *value = kvs_hash_get(hash, key);
|
||||||
|
if (!value) return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
int main() {
|
||||||
|
|
||||||
|
kvs_hash_create(&hash);
|
||||||
|
|
||||||
|
kvs_hash_set(&hash, "Teacher1", "King");
|
||||||
|
kvs_hash_set(&hash, "Teacher2", "Darren");
|
||||||
|
kvs_hash_set(&hash, "Teacher3", "Mark");
|
||||||
|
kvs_hash_set(&hash, "Teacher4", "Vico");
|
||||||
|
kvs_hash_set(&hash, "Teacher5", "Nick");
|
||||||
|
|
||||||
|
char *value1 = kvs_hash_get(&hash, "Teacher1");
|
||||||
|
printf("Teacher1 : %s\n", value1);
|
||||||
|
|
||||||
|
int ret = kvs_hash_mod(&hash, "Teacher1", "King1");
|
||||||
|
printf("mode Teacher1 ret : %d\n", ret);
|
||||||
|
|
||||||
|
char *value2 = kvs_hash_get(&hash, "Teacher1");
|
||||||
|
printf("Teacher2 : %s\n", value1);
|
||||||
|
|
||||||
|
ret = kvs_hash_del(&hash, "Teacher1");
|
||||||
|
printf("delete Teacher1 ret : %d\n", ret);
|
||||||
|
|
||||||
|
ret = kvs_hash_exist(&hash, "Teacher1");
|
||||||
|
printf("Exist Teacher1 ret : %d\n", ret);
|
||||||
|
|
||||||
|
kvs_hash_destory(&hash);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -498,8 +498,9 @@ int kvs_rbtree_set(kvs_rbtree_t *inst, char *key, char *value) {
|
|||||||
char* kvs_rbtree_get(kvs_rbtree_t *inst, char *key) {
|
char* kvs_rbtree_get(kvs_rbtree_t *inst, char *key) {
|
||||||
|
|
||||||
if (!inst || !key) return NULL;
|
if (!inst || !key) return NULL;
|
||||||
|
|
||||||
rbtree_node *node = rbtree_search(inst, key);
|
rbtree_node *node = rbtree_search(inst, key);
|
||||||
|
if (!node) return NULL; // no exist
|
||||||
|
if (node == inst->nil) return NULL;
|
||||||
|
|
||||||
return node->value;
|
return node->value;
|
||||||
|
|
||||||
@@ -524,7 +525,8 @@ int kvs_rbtree_mod(kvs_rbtree_t *inst, char *key, char *value) {
|
|||||||
|
|
||||||
rbtree_node *node = rbtree_search(inst, key);
|
rbtree_node *node = rbtree_search(inst, key);
|
||||||
if (!node) return 1; // no exist
|
if (!node) return 1; // no exist
|
||||||
|
if (node == inst->nil) return 1;
|
||||||
|
|
||||||
kvs_free(node->value);
|
kvs_free(node->value);
|
||||||
|
|
||||||
node->value = kvs_malloc(strlen(value) + 1);
|
node->value = kvs_malloc(strlen(value) + 1);
|
||||||
@@ -543,6 +545,7 @@ int kvs_rbtree_exist(kvs_rbtree_t *inst, char *key) {
|
|||||||
|
|
||||||
rbtree_node *node = rbtree_search(inst, key);
|
rbtree_node *node = rbtree_search(inst, key);
|
||||||
if (!node) return 1; // no exist
|
if (!node) return 1; // no exist
|
||||||
|
if (node == inst->nil) return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
140
kvs_skiptable.c
Executable file
140
kvs_skiptable.c
Executable file
@@ -0,0 +1,140 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define MAX_LEVEL 6
|
||||||
|
|
||||||
|
typedef struct Node {
|
||||||
|
int key;
|
||||||
|
int value;
|
||||||
|
struct Node** forward;
|
||||||
|
} Node;
|
||||||
|
|
||||||
|
typedef struct SkipList {
|
||||||
|
int level;
|
||||||
|
Node* header;
|
||||||
|
} SkipList;
|
||||||
|
|
||||||
|
Node* createNode(int level, int key, int value) {
|
||||||
|
Node* newNode = (Node*)malloc(sizeof(Node));
|
||||||
|
newNode->key = key;
|
||||||
|
newNode->value = value;
|
||||||
|
newNode->forward = (Node**)malloc((level + 1) * sizeof(Node*));
|
||||||
|
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
SkipList* createSkipList() {
|
||||||
|
SkipList* skipList = (SkipList*)malloc(sizeof(SkipList));
|
||||||
|
skipList->level = 0;
|
||||||
|
|
||||||
|
skipList->header = createNode(MAX_LEVEL, -1, -1);
|
||||||
|
|
||||||
|
for (int i = 0; i <= MAX_LEVEL; ++i) {
|
||||||
|
skipList->header->forward[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return skipList;
|
||||||
|
}
|
||||||
|
|
||||||
|
int randomLevel() {
|
||||||
|
int level = 0;
|
||||||
|
while (rand() < RAND_MAX / 2 && level < MAX_LEVEL)
|
||||||
|
level++;
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool insert(SkipList* skipList, int key, int value) {
|
||||||
|
Node* update[MAX_LEVEL + 1];
|
||||||
|
Node* current = skipList->header;
|
||||||
|
|
||||||
|
for (int i = skipList->level; i >= 0; --i) {
|
||||||
|
while (current->forward[i] != NULL && current->forward[i]->key < key)
|
||||||
|
current = current->forward[i];
|
||||||
|
update[i] = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = current->forward[0];
|
||||||
|
|
||||||
|
if (current == NULL || current->key != key) {
|
||||||
|
int level = randomLevel();
|
||||||
|
|
||||||
|
if (level > skipList->level) {
|
||||||
|
for (int i = skipList->level + 1; i <= level; ++i)
|
||||||
|
update[i] = skipList->header;
|
||||||
|
skipList->level = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node* newNode = createNode(level, key, value);
|
||||||
|
|
||||||
|
for (int i = 0; i <= level; ++i) {
|
||||||
|
newNode->forward[i] = update[i]->forward[i];
|
||||||
|
update[i]->forward[i] = newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Inserted key %d\n", key);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
printf("Key %d already exists\n", key);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void display(SkipList* skipList) {
|
||||||
|
printf("Skip List:\n");
|
||||||
|
|
||||||
|
for (int i = 0; i <= skipList->level; ++i) {
|
||||||
|
Node* node = skipList->header->forward[i];
|
||||||
|
printf("Level %d: ", i);
|
||||||
|
|
||||||
|
while (node != NULL) {
|
||||||
|
printf("%d ", node->key);
|
||||||
|
node = node->forward[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool search(SkipList* skipList, int key) {
|
||||||
|
Node* current = skipList->header;
|
||||||
|
|
||||||
|
for (int i = skipList->level; i >= 0; --i) {
|
||||||
|
while (current->forward[i] != NULL && current->forward[i]->key < key)
|
||||||
|
current = current->forward[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
current = current -> forward[0];
|
||||||
|
|
||||||
|
if(current && current -> key == key){
|
||||||
|
printf("Key %d found with value %d\n", key, current->value);
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
printf("Key %d not found\n", key);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
SkipList* skipList = createSkipList();
|
||||||
|
|
||||||
|
insert(skipList, 3, 30);
|
||||||
|
insert(skipList, 6, 60);
|
||||||
|
insert(skipList, 2, 20);
|
||||||
|
insert(skipList, 4, 40);
|
||||||
|
|
||||||
|
display(skipList);
|
||||||
|
|
||||||
|
search(skipList, 3);
|
||||||
|
search(skipList, 7);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
71
kvstore.c
71
kvstore.c
@@ -13,7 +13,9 @@ extern kvs_array_t global_array;
|
|||||||
extern kvs_rbtree_t global_rbtree;
|
extern kvs_rbtree_t global_rbtree;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ENABLE_HASH
|
||||||
|
extern kvs_hash_t global_hash;
|
||||||
|
#endif
|
||||||
|
|
||||||
void *kvs_malloc(size_t size) {
|
void *kvs_malloc(size_t size) {
|
||||||
return malloc(size);
|
return malloc(size);
|
||||||
@@ -26,7 +28,8 @@ void kvs_free(void *ptr) {
|
|||||||
|
|
||||||
const char *command[] = {
|
const char *command[] = {
|
||||||
"SET", "GET", "DEL", "MOD", "EXIST",
|
"SET", "GET", "DEL", "MOD", "EXIST",
|
||||||
"RSET", "RGET", "RDEL", "RMOD", "REXIST"
|
"RSET", "RGET", "RDEL", "RMOD", "REXIST",
|
||||||
|
"HSET", "HGET", "HDEL", "HMOD", "HEXIST"
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -43,6 +46,12 @@ enum {
|
|||||||
KVS_CMD_RDEL,
|
KVS_CMD_RDEL,
|
||||||
KVS_CMD_RMOD,
|
KVS_CMD_RMOD,
|
||||||
KVS_CMD_REXIST,
|
KVS_CMD_REXIST,
|
||||||
|
// hash
|
||||||
|
KVS_CMD_HSET,
|
||||||
|
KVS_CMD_HGET,
|
||||||
|
KVS_CMD_HDEL,
|
||||||
|
KVS_CMD_HMOD,
|
||||||
|
KVS_CMD_HEXIST,
|
||||||
|
|
||||||
KVS_CMD_COUNT,
|
KVS_CMD_COUNT,
|
||||||
};
|
};
|
||||||
@@ -195,6 +204,56 @@ int kvs_filter_protocol(char **tokens, int count, char *response) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
#if ENABLE_HASH
|
||||||
|
case KVS_CMD_HSET:
|
||||||
|
ret = kvs_hash_set(&global_hash ,key, value);
|
||||||
|
if (ret < 0) {
|
||||||
|
length = sprintf(response, "ERROR\r\n");
|
||||||
|
} else if (ret == 0) {
|
||||||
|
length = sprintf(response, "OK\r\n");
|
||||||
|
} else {
|
||||||
|
length = sprintf(response, "EXIST\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case KVS_CMD_HGET: {
|
||||||
|
char *result = kvs_hash_get(&global_hash, key);
|
||||||
|
if (result == NULL) {
|
||||||
|
length = sprintf(response, "NO EXIST\r\n");
|
||||||
|
} else {
|
||||||
|
length = sprintf(response, "%s\r\n", result);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case KVS_CMD_HDEL:
|
||||||
|
ret = kvs_hash_del(&global_hash ,key);
|
||||||
|
if (ret < 0) {
|
||||||
|
length = sprintf(response, "ERROR\r\n");
|
||||||
|
} else if (ret == 0) {
|
||||||
|
length = sprintf(response, "OK\r\n");
|
||||||
|
} else {
|
||||||
|
length = sprintf(response, "NO EXIST\r\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KVS_CMD_HMOD:
|
||||||
|
ret = kvs_hash_mod(&global_hash ,key, value);
|
||||||
|
if (ret < 0) {
|
||||||
|
length = sprintf(response, "ERROR\r\n");
|
||||||
|
} else if (ret == 0) {
|
||||||
|
length = sprintf(response, "OK\r\n");
|
||||||
|
} else {
|
||||||
|
length = sprintf(response, "NO EXIST\r\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KVS_CMD_HEXIST:
|
||||||
|
ret = kvs_hash_exist(&global_hash ,key);
|
||||||
|
if (ret == 0) {
|
||||||
|
length = sprintf(response, "EXIST\r\n");
|
||||||
|
} else {
|
||||||
|
length = sprintf(response, "NO EXIST\r\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
@@ -243,6 +302,11 @@ int init_kvengine(void) {
|
|||||||
kvs_rbtree_create(&global_rbtree);
|
kvs_rbtree_create(&global_rbtree);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if ENABLE_HASH
|
||||||
|
memset(&global_hash, 0, sizeof(kvs_hash_t));
|
||||||
|
kvs_hash_create(&global_hash);
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,6 +317,9 @@ void dest_kvengine(void) {
|
|||||||
#if ENABLE_RBTREE
|
#if ENABLE_RBTREE
|
||||||
kvs_rbtree_destory(&global_rbtree);
|
kvs_rbtree_destory(&global_rbtree);
|
||||||
#endif
|
#endif
|
||||||
|
#if ENABLE_HASH
|
||||||
|
kvs_hash_destory(&global_hash);
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
48
kvstore.h
48
kvstore.h
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
#define ENABLE_ARRAY 1
|
#define ENABLE_ARRAY 1
|
||||||
#define ENABLE_RBTREE 1
|
#define ENABLE_RBTREE 1
|
||||||
|
#define ENABLE_HASH 1
|
||||||
|
|
||||||
|
|
||||||
typedef int (*msg_handler)(char *msg, int length, char *response);
|
typedef int (*msg_handler)(char *msg, int length, char *response);
|
||||||
@@ -104,6 +104,52 @@ int kvs_rbtree_exist(kvs_rbtree_t *inst, char *key);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if ENABLE_HASH
|
||||||
|
|
||||||
|
#define MAX_KEY_LEN 128
|
||||||
|
#define MAX_VALUE_LEN 512
|
||||||
|
#define MAX_TABLE_SIZE 1024
|
||||||
|
|
||||||
|
#define ENABLE_KEY_POINTER 1
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct hashnode_s {
|
||||||
|
#if ENABLE_KEY_POINTER
|
||||||
|
char *key;
|
||||||
|
char *value;
|
||||||
|
#else
|
||||||
|
char key[MAX_KEY_LEN];
|
||||||
|
char value[MAX_VALUE_LEN];
|
||||||
|
#endif
|
||||||
|
struct hashnode_s *next;
|
||||||
|
|
||||||
|
} hashnode_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct hashtable_s {
|
||||||
|
|
||||||
|
hashnode_t **nodes; //* change **,
|
||||||
|
|
||||||
|
int max_slots;
|
||||||
|
int count;
|
||||||
|
|
||||||
|
} hashtable_t;
|
||||||
|
|
||||||
|
typedef struct hashtable_s kvs_hash_t;
|
||||||
|
|
||||||
|
|
||||||
|
int kvs_hash_create(kvs_hash_t *hash);
|
||||||
|
void kvs_hash_destory(kvs_hash_t *hash);
|
||||||
|
int kvs_hash_set(hashtable_t *hash, char *key, char *value);
|
||||||
|
char * kvs_hash_get(kvs_hash_t *hash, char *key);
|
||||||
|
int kvs_hash_mod(kvs_hash_t *hash, char *key, char *value);
|
||||||
|
int kvs_hash_del(kvs_hash_t *hash, char *key);
|
||||||
|
int kvs_hash_exist(kvs_hash_t *hash, char *key);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
121
testcase.c
121
testcase.c
@@ -90,9 +90,9 @@ void array_testcase(int connfd) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void array_testcase_10w(int connfd) {
|
void array_testcase_1w(int connfd) {
|
||||||
|
|
||||||
int count = 1000;
|
int count = 10000;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
struct timeval tv_begin;
|
struct timeval tv_begin;
|
||||||
@@ -117,7 +117,7 @@ void array_testcase_10w(int connfd) {
|
|||||||
|
|
||||||
int time_used = TIME_SUB_MS(tv_end, tv_begin); // ms
|
int time_used = TIME_SUB_MS(tv_end, tv_begin); // ms
|
||||||
|
|
||||||
printf("array testcase --> time_used: %d, qps: %d\n", time_used, 9000 * 1000 / time_used);
|
printf("array testcase --> time_used: %d, qps: %d\n", time_used, 90000 * 1000 / time_used);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,34 +125,129 @@ void array_testcase_10w(int connfd) {
|
|||||||
void rbtree_testcase(int connfd) {
|
void rbtree_testcase(int connfd) {
|
||||||
|
|
||||||
testcase(connfd, "RSET Teacher King", "OK\r\n", "RSET-Teacher");
|
testcase(connfd, "RSET Teacher King", "OK\r\n", "RSET-Teacher");
|
||||||
testcase(connfd, "RGET Teacher", "King\r\n", "RGET-Teacher");
|
testcase(connfd, "RGET Teacher", "King\r\n", "RGET-King-Teacher");
|
||||||
testcase(connfd, "RMOD Teacher Darren", "OK\r\n", "RMOD-Teacher");
|
testcase(connfd, "RMOD Teacher Darren", "OK\r\n", "RMOD-D-Teacher");
|
||||||
testcase(connfd, "RGET Teacher", "Darren\r\n", "RGET-Teacher");
|
testcase(connfd, "RGET Teacher", "Darren\r\n", "RGET-Darren-Teacher");
|
||||||
testcase(connfd, "REXIST Teacher", "EXIST\r\n", "RGET-Teacher");
|
testcase(connfd, "REXIST Teacher", "EXIST\r\n", "REXIST-Teacher");
|
||||||
testcase(connfd, "RDEL Teacher", "OK\r\n", "RDEL-Teacher");
|
testcase(connfd, "RDEL Teacher", "OK\r\n", "RDEL-Teacher");
|
||||||
testcase(connfd, "RGET Teacher", "NO EXIST\r\n", "RGET-Teacher");
|
testcase(connfd, "RGET Teacher", "NO EXIST\r\n", "RGET-K-Teacher");
|
||||||
testcase(connfd, "RMOD Teacher KING", "NO EXIST\r\n", "RMOD-Teacher");
|
testcase(connfd, "RMOD Teacher KING", "NO EXIST\r\n", "RMOD-K-Teacher");
|
||||||
testcase(connfd, "REXIST Teacher", "NO EXIST\r\n", "RGET-Teacher");
|
testcase(connfd, "REXIST Teacher", "NO EXIST\r\n", "REXIST-Teacher");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rbtree_testcase_1w(int connfd) {
|
||||||
|
|
||||||
|
int count = 10000;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
struct timeval tv_begin;
|
||||||
|
gettimeofday(&tv_begin, NULL);
|
||||||
|
|
||||||
|
for (i = 0;i < count;i ++) {
|
||||||
|
|
||||||
|
testcase(connfd, "RSET Teacher King", "OK\r\n", "RSET-Teacher");
|
||||||
|
testcase(connfd, "RGET Teacher", "King\r\n", "RGET-King-Teacher");
|
||||||
|
testcase(connfd, "RMOD Teacher Darren", "OK\r\n", "RMOD-D-Teacher");
|
||||||
|
testcase(connfd, "RGET Teacher", "Darren\r\n", "RGET-Darren-Teacher");
|
||||||
|
testcase(connfd, "REXIST Teacher", "EXIST\r\n", "REXIST-Teacher");
|
||||||
|
testcase(connfd, "RDEL Teacher", "OK\r\n", "RDEL-Teacher");
|
||||||
|
testcase(connfd, "RGET Teacher", "NO EXIST\r\n", "RGET-K-Teacher");
|
||||||
|
testcase(connfd, "RMOD Teacher KING", "NO EXIST\r\n", "RMOD-K-Teacher");
|
||||||
|
testcase(connfd, "REXIST Teacher", "NO EXIST\r\n", "REXIST-Teacher");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timeval tv_end;
|
||||||
|
gettimeofday(&tv_end, NULL);
|
||||||
|
|
||||||
|
int time_used = TIME_SUB_MS(tv_end, tv_begin); // ms
|
||||||
|
|
||||||
|
printf("rbtree testcase --> time_used: %d, qps: %d\n", time_used, 90000 * 1000 / time_used);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void rbtree_testcase_3w(int connfd) {
|
||||||
|
|
||||||
|
int count = 10000;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
struct timeval tv_begin;
|
||||||
|
gettimeofday(&tv_begin, NULL);
|
||||||
|
|
||||||
|
for (i = 0;i < count;i ++) {
|
||||||
|
|
||||||
|
char cmd[128] = {0};
|
||||||
|
snprintf(cmd, 128, "RSET Teacher%d King%d", i, i);
|
||||||
|
testcase(connfd, cmd, "OK\r\n", "RSET-Teacher");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0;i < count;i ++) {
|
||||||
|
|
||||||
|
char cmd[128] = {0};
|
||||||
|
snprintf(cmd, 128, "RGET Teacher%d", i);
|
||||||
|
|
||||||
|
char result[128] = {0};
|
||||||
|
snprintf(result, 128, "King%d\r\n", i);
|
||||||
|
|
||||||
|
testcase(connfd, cmd, result, "RGET-King-Teacher");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0;i < count;i ++) {
|
||||||
|
|
||||||
|
char cmd[128] = {0};
|
||||||
|
snprintf(cmd, 128, "RMOD Teacher%d King%d", i, i);
|
||||||
|
testcase(connfd, cmd, "OK\r\n", "RGET-King-Teacher");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct timeval tv_end;
|
||||||
|
gettimeofday(&tv_end, NULL);
|
||||||
|
|
||||||
|
int time_used = TIME_SUB_MS(tv_end, tv_begin); // ms
|
||||||
|
|
||||||
|
printf("rbtree testcase --> time_used: %d, qps: %d\n", time_used, 30000 * 1000 / time_used);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void hash_testcase(int connfd) {
|
||||||
|
|
||||||
|
testcase(connfd, "HSET Teacher King", "OK\r\n", "HSET-Teacher");
|
||||||
|
testcase(connfd, "HGET Teacher", "King\r\n", "HGET-King-Teacher");
|
||||||
|
testcase(connfd, "HMOD Teacher Darren", "OK\r\n", "HMOD-D-Teacher");
|
||||||
|
testcase(connfd, "HGET Teacher", "Darren\r\n", "HGET-Darren-Teacher");
|
||||||
|
testcase(connfd, "HEXIST Teacher", "EXIST\r\n", "HEXIST-Teacher");
|
||||||
|
testcase(connfd, "HDEL Teacher", "OK\r\n", "HDEL-Teacher");
|
||||||
|
testcase(connfd, "HGET Teacher", "NO EXIST\r\n", "HGET-K-Teacher");
|
||||||
|
testcase(connfd, "HMOD Teacher KING", "NO EXIST\r\n", "HMOD-K-Teacher");
|
||||||
|
testcase(connfd, "HEXIST Teacher", "NO EXIST\r\n", "HEXIST-Teacher");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// testcase 192.168.243.131 2000
|
// testcase 192.168.243.131 2000
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
if (argc != 3) {
|
if (argc != 4) {
|
||||||
printf("arg error\n");
|
printf("arg error\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *ip = argv[1];
|
char *ip = argv[1];
|
||||||
int port = atoi(argv[2]);
|
int port = atoi(argv[2]);
|
||||||
|
int mode = atoi(argv[3]);
|
||||||
|
|
||||||
int connfd = connect_tcpserver(ip, port);
|
int connfd = connect_tcpserver(ip, port);
|
||||||
|
|
||||||
rbtree_testcase(connfd);
|
if (mode == 0) {
|
||||||
//array_testcase_10w(connfd);
|
rbtree_testcase_1w(connfd);
|
||||||
|
} else if (mode == 1) {
|
||||||
|
rbtree_testcase_3w(connfd);
|
||||||
|
} else if (mode == 2) {
|
||||||
|
array_testcase_1w(connfd);
|
||||||
|
} else if (mode == 3) {
|
||||||
|
hash_testcase(connfd);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user