


#ifndef __KV_STORE_H__
#define __KV_STORE_H__


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include "server.h"


#define NETWORK_REACTOR 	0
#define NETWORK_PROACTOR	1
#define NETWORK_NTYCO		2

#define NETWORK_SELECT		NETWORK_REACTOR


#define KVS_MAX_TOKENS		128

#define ENABLE_ARRAY		1
#define ENABLE_RBTREE		1
#define ENABLE_HASH			1

#define NEW_KVSTORE 	1

#define BIN_SAFE		1

#define KVS_CMD_LOG_FILE 	"kvs_cmd_log.db"
#define KVS_ARRAY_FILE 		"kvs_snap_array.db"
#define KVS_RBTREE_FILE 	"kvs_snap_rbtree.db"
#define KVS_HASH_FILE 		"kvs_snap_hash.db"



// typedef int (*msg_handler)(char *msg, int length, char *response);
// typedef int (*msg_handler)(char *request, int request_length, char *response, int *response_length);
typedef int (*msg_handler)(struct conn* conn);

extern int reactor_start(unsigned short port, msg_handler handler, const char *m_ip, int m_port);
extern int proactor_start(unsigned short port, msg_handler handler);
extern int ntyco_start(unsigned short port, msg_handler handler);

extern int init_cmd_log(const char *file, int *logfd);
extern int destroy_cmd_log(int logfd);
extern int kvs_save_cmd_to_logfile(const uint8_t *cmd, size_t len, int logfd);
extern int kvs_replay_log(const char *logfile, int logfd);
extern int ksv_clear_log(int logfd);

extern int try_connect_master(char *ip, int port);
void build_thread_to_sync(const uint8_t *offset, struct conn* conn);

#if ENABLE_ARRAY

#if BIN_SAFE
#define KVS_ARRAY_SIZE		1024

typedef struct kvs_array_item_s {
    uint8_t *key;
    uint32_t key_len;

    uint8_t *value;
    uint32_t value_len;
} kvs_array_item_t;


typedef struct kvs_array_s {
    kvs_array_item_t *table;
    int total;  // 元素上界
} kvs_array_t;

int  kvs_array_create(kvs_array_t *inst);
void kvs_array_destroy(kvs_array_t *inst);
int kvs_array_set_bin(kvs_array_t *inst,
                      const void *key, uint32_t key_len,
                      const void *value, uint32_t value_len);
void *kvs_array_get_bin(kvs_array_t *inst,
                              const void *key, uint32_t key_len,
                              uint32_t *out_value_len);
int kvs_array_del_bin(kvs_array_t *inst, const void *key, uint32_t key_len);
int kvs_array_mod_bin(kvs_array_t *inst,
                      const void *key, uint32_t key_len,
                      const void *value, uint32_t value_len);
int kvs_array_exist_bin(kvs_array_t *inst, const void *key, uint32_t key_len);


int kvs_array_save(kvs_array_t *inst, const char* filename);
int kvs_array_load(kvs_array_t *inst, const char* filename);

#else 
typedef struct kvs_array_item_s {
	char *key;
	char *value;
} kvs_array_item_t;

#define KVS_ARRAY_SIZE		1024

typedef struct kvs_array_s {
	kvs_array_item_t *table;
	int idx;
	int total;
} kvs_array_t;

int kvs_array_create(kvs_array_t *inst);
void kvs_array_destroy(kvs_array_t *inst);

int kvs_array_set(kvs_array_t *inst, char *key, char *value);
char* kvs_array_get(kvs_array_t *inst, char *key);
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_exist(kvs_array_t *inst, char *key);
#endif 

#endif


#if ENABLE_RBTREE

#define RED				1
#define BLACK 			2

#if BIN_SAFE
typedef uint8_t KEY_TYPE; // key

typedef struct _rbtree_node {
	unsigned char color;
	struct _rbtree_node *right;
	struct _rbtree_node *left;
	struct _rbtree_node *parent;
	KEY_TYPE *key;
	uint32_t key_len;
	KEY_TYPE *value;
	uint32_t value_len;
} rbtree_node;

typedef struct _rbtree {
    rbtree_node *root;
    rbtree_node *nil;
} rbtree;

typedef struct _rbtree kvs_rbtree_t;

int kvs_rbtree_create(kvs_rbtree_t *inst);
void kvs_rbtree_destroy(kvs_rbtree_t *inst);
int kvs_rbtree_set(kvs_rbtree_t *inst, const void *key, uint32_t key_len, const void *value, uint32_t value_len);
void* kvs_rbtree_get(kvs_rbtree_t *inst, const void *key, uint32_t key_len, uint32_t *out_valuelen);
int kvs_rbtree_del(rbtree *inst, const void *key, uint32_t key_len);
int kvs_rbtree_mod(kvs_rbtree_t *inst, const void *key, uint32_t key_len, const void *value, uint32_t value_len);
int kvs_rbtree_exist(kvs_rbtree_t *inst, const void *key, uint32_t key_len);

int kvs_rbtree_save(kvs_rbtree_t *inst, const char* filename);
int kvs_rbtree_load(kvs_rbtree_t *inst, const char* filename);
#else
#define ENABLE_KEY_CHAR		1

#if ENABLE_KEY_CHAR
typedef char* KEY_TYPE;
#else
typedef int KEY_TYPE; // key
#endif

typedef struct _rbtree_node {
	unsigned char color;
	struct _rbtree_node *right;
	struct _rbtree_node *left;
	struct _rbtree_node *parent;
	KEY_TYPE key;
	void *value;
} rbtree_node;

typedef struct _rbtree {
	rbtree_node *root;
	rbtree_node *nil;
} rbtree;


typedef struct _rbtree kvs_rbtree_t;

int kvs_rbtree_create(kvs_rbtree_t *inst);
void kvs_rbtree_destroy(kvs_rbtree_t *inst);
int kvs_rbtree_set(kvs_rbtree_t *inst, char *key, char *value);
char* kvs_rbtree_get(kvs_rbtree_t *inst, char *key);
int kvs_rbtree_del(kvs_rbtree_t *inst, char *key);
int kvs_rbtree_mod(kvs_rbtree_t *inst, char *key, char *value);
int kvs_rbtree_exist(kvs_rbtree_t *inst, char *key);
#endif


#endif


#if ENABLE_HASH


#if BIN_SAFE
#define MAX_TABLE_SIZE 1024
typedef struct hashnode_s {
    uint8_t *key;
    size_t   key_len;

    uint8_t *value;
    size_t   value_len;

    struct hashnode_s *next;
} hashnode_t;

typedef struct hashtable_s {
    hashnode_t **nodes;
    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_destroy(kvs_hash_t *hash);
int kvs_hash_set_bin(kvs_hash_t *h, const void *key, uint32_t key_len, const void *value, uint32_t value_len);
void *kvs_hash_get_bin(kvs_hash_t *h, const void *key, uint32_t key_len, uint32_t *out_value_len);
int kvs_hash_get_copy_bin(kvs_hash_t *h, const void *key, uint32_t key_len, void **out_buf, uint32_t *out_len);
int kvs_hash_mod_bin(kvs_hash_t *h, const void *key, uint32_t key_len, const void *value, uint32_t value_len);
int kvs_hash_del_bin(kvs_hash_t *h, const void *key, uint32_t key_len);
int kvs_hash_exist_bin(kvs_hash_t *h, const void *key, uint32_t key_len);
int kvs_hash_count(kvs_hash_t *h);

int kvs_hash_save(kvs_hash_t *inst, const char* filename);
int kvs_hash_load(kvs_hash_t *inst, const char* filename);
#else

#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_destroy(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




#endif



