快照数据库 Snapshot DB

源码下载:http://download.csdn.net/detail/liuzhuchen/9534475

任务描述

在这个任务中,我们将开发一个名为“快照数据库”的key value存储程序,在C编程中使用动态的数据结构,确保不发生内存错误。数据库中的每个条目都被一个唯一的关键字符串标识,并且包含一个动态大小的整型列表。

实施细则

编写一个程序,用C实现快照,如下面的示例所示。您可以假设我们的测试用例将只包含有效的输入命令,而不会导致任何整数溢出。按键是区分大小写的,不包含空格。命令是区分大小写的。输入值被索引从1。快照从1被索引,并且是程序的生命周期内是唯一的。键,条目和快照将输出从最近添加的顺序,至少最近添加。在实验室机器上建立和运行时,要产生没有错误,并从标准输入和写入到标准输出。您的程序输出必须与在实例中显示的精确输出格式相匹配。

为了获得满分,你的程序必须释放所有的动态内存分配。系统会内存检查使用地址情况。如果您的程序为一个给定的测试用例产生正确的输出,并且不释放它分配的所有内存,那么它将不通过给定的测试用例。

命令

你的程序应该执行以下命令,看这些例子,他们是如何工作的。
• If a does not exist in the current state, output: no such key
• If a does not exist in the database, output: no such snapshot
• If an does not exist in an entry, output: index out of range

BYE clear database and exit
HELP display this help message
LIST KEYS displays all keys in current state
LIST ENTRIES displays all entries in current state
LIST SNAPSHOTS displays all snapshots in the database
GET <key> displays entry values
DEL <key> deletes entry from current state
PURGE <key> deletes entry from current state and snapshots
SET <key> <value ...> sets entry values
PUSH <key> <value ...> pushes values to the front
APPEND <key> <value ...> appends values to the back
PICK <key> <index> displays value at index
PLUCK <key> <index> displays and removes value at index
POP <key> displays and removes the front value
DROP <id> deletes snapshot
ROLLBACK <id> restores to snapshot and deletes newer snapshots
CHECKOUT <id> replaces current state with a copy of snapshot
SNAPSHOT saves the current state as a snapshot
MIN <key> displays minimum value
MAX <key> displays maximum value
SUM <key> displays sum of values
LEN <key> displays number of values
REV <key> reverses order of values
UNIQ <key> removes repeated adjacent values
SORT <key> sorts values in ascending order
DIFF <key> <key ...> displays set difference of values in keys
INTER <key> <key ...> displays set intersection of values in keys
UNION <key> <key ...> displays set union of values in keys
> BYE
bye

Examples

> LIST KEYS
no keys
> LIST ENTRIES
no entries
> LIST SNAPSHOTS
no snapshots
> SET a 1
ok
> GET a
[1]
> POP a
1
> GET a
[]
> POP a
nil
> PUSH a 2 1
ok
> GET a
[1 2]
> APPEND a 3 4
ok
> GET a
[1 2 3 4]
> DEL a
ok
> DEL a
no such key
> BYE
bye
> SET a 1
ok
> SET b 2 3
ok
> LIST KEYS
b
a
> LIST ENTRIES
b [2 3]
a [1]
> LIST SNAPSHOTS
no snapshots
> PICK a 0
index out of range
> PICK b 1
2
> GET b
[2 3]
> PLUCK b 2
3
> GET b
[2]
> DEL b
ok
> GET b
no such key
> PURGE b
ok
> BYE
bye
Operating Systems and Machine Principles Page 4 of 6
> DROP 1
no such snapshot
> ROLLBACK 1
no such snapshot
> SET a 1 2
ok
> SET b 3 4
ok
> LIST ENTRIES
b [3 4]
a [1 2]
> SNAPSHOT
saved as snapshot 1
> SET c 5 6
ok
> LIST ENTRIES
c [5 6]
b [3 4]
a [1 2]
> SNAPSHOT
saved as snapshot 2
> PURGE b
ok
> ROLLBACK 1
ok
> CHECKOUT 2
no such snapshot
> LIST ENTRIES
a [1 2]
> LIST SNAPSHOTS
1
> BYE
bye

代码

snapshot.h

#ifndef SNAPSHOT_H
#define SNAPSHOT_H

#define MAX_KEY 16
#define MAX_LINE 1024

#define RET_YES 0
#define RET_NO 1



typedef struct entry entry;
typedef struct snapshot snapshot;

struct entry {
    char key[MAX_KEY];
    int * values;
    size_t length;
    entry * next;
    entry * prev;
};
struct snapshot {
    int id;
    entry * entries;
    snapshot * next;
    snapshot * prev;
};


extern entry cur_entry_h;
extern snapshot g_snapshot_h;
extern snapshot *cur_snapshot_h;

#endif

snapshot.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "snapshot.h"
#include "snapshot_cmd.h"
#include "snapshot_list.h"

entry cur_entry_h;
snapshot g_snapshot_h;
snapshot *cur_snapshot_h;



void run_environment_init()
{
    entry_head_init(&cur_entry_h);
    snapshot_head_init(&g_snapshot_h);
    cur_snapshot_h = NULL;
}


void run_environment_destroy()
{
    entry_delete_list(&cur_entry_h);
    snapshot_delete_list(&g_snapshot_h);
    return ;
}


/*
int cmp_asc(const void *a, const void *b)
{
    return *(int *)a>*(int *)b;
}
void qsort_to_repeat(int *data, int *len)
{
    int new_len = 0;
    int i,j;

    qsort(data, *len, sizeof(int), cmp_asc);

    for(i=1;i<*len;i++){
        if(data[new_len]!=data[i]){
            new_len++;
            data[new_len]=data[i];
        }
    }
    *len = new_len+1;
}*/

int main(int args, char **argv)
{
    char get_cmd[MAX_LINE];
    int get_cmd_len=0;
    int get_cmd_id;
    int ret;    
    string_segmentation_s string_array;
    FILE *fp=NULL;



/*
    int data[10]={
        1,2,3,4,5,2,7,8,9,20
    };
    printf("%d\n", qsort_to_repeat(data, 10));
    return 0;*/

    run_environment_init();
    if(args > 1){
        fp = fopen(argv[1], "r");
        if(fp==NULL){
            printf("ERROR: fail to read file [%s].\n", argv[1]);
            return 0;
        }
    }


    while(1){
        if(args > 1){
            ret = cmd_get_str_from_file(get_cmd, &get_cmd_len, fp);
            printf(">%s\n", get_cmd);           
        }
        else{
            ret = cmd_get_str_from_stdin(get_cmd, &get_cmd_len);            
        }
        if(get_cmd[0] == '\0')continue;
        if(ret == RET_YES){
            string_segmentation(' ', get_cmd, 0, &string_array);
            get_cmd_id = cmd_get_id(&string_array);
            if(get_cmd_id >= CMD_NUM){
                printf("Invalid command, enter the HELP command to view the help.\n\n");
                string_segmentation_free(&string_array);
                continue;
            }
            if(get_cmd_id == CMD_BYE){
                run_environment_destroy();
                printf("bye\n");
                string_segmentation_free(&string_array);
                //cmd_bye();
                break;
            }
            cmd_dispatch(get_cmd_id, &string_array);
            string_segmentation_free(&string_array);
        }
        printf("\n");
    }

    if(fp != NULL)fclose(fp);
    return 0;
}

snapshot_cmd.h

#ifndef SNAPSHOT_CMD_H
#define SNAPSHOT_CMD_H



enum g_cmd{
    CMD_BYE,
    CMD_HELP,
    CMD_LIST_KEYS,
    CMD_LIST_ENTRIES,
    CMD_LIST_SNAPSHOTS,
    CMD_GET,
    CMD_DEL,
    CMD_PURGE,
    CMD_SET,
    CMD_PUSH,
    CMD_APPEND,
    CMD_PICK,
    CMD_PLUCK,
    CMD_POP,
    CMD_DROP,
    CMD_ROLLBACK,
    CMD_CHECKOUT,
    CMD_SNAPSHOT,
    CMD_MIN,
    CMD_MAX,
    CMD_SUM,
    CMD_LEN,
    CMD_REV,
    CMD_UNIQ,
    CMD_SORT,
    CMD_DIFF,
    CMD_INTER,
    CMD_UNION,
    CMD_NUM
};

extern char *g_cmd_str[CMD_NUM];
extern char *g_cmd_help[CMD_NUM];

typedef struct string_segmentation_struct
{
    char **strings;
    int len;
    char *internal_buf;
}string_segmentation_s;

extern void string_segmentation(char delimiter, char *string, int limit, string_segmentation_s * string_array);
extern void string_segmentation_free(string_segmentation_s *string_array);


extern void snapshot_free(snapshot *snapshot_h);

extern int cmd_get_str_from_file(char *cmd, int *cmd_len, FILE * fp);
extern int cmd_get_str_from_stdin(char cmd[], int *cmd_len);
extern int cmd_get_id(string_segmentation_s *string_array);


extern void cmd_dispatch(int cmd_id, string_segmentation_s *string_array);

#endif

snapshot_cmd.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include "snapshot.h"
#include "snapshot_cmd.h"
#include "snapshot_list.h"

char *g_cmd_str[CMD_NUM]={
    "BYE",
    "HELP",
    "LIST KEYS",
    "LIST ENTRIES",
    "LIST SNAPSHOTS",
    "GET",
    "DEL",
    "PURGE",
    "SET",
    "PUSH",
    "APPEND",
    "PICK",
    "PLUCK",
    "POP",
    "DROP",
    "ROLLBACK",
    "CHECKOUT",
    "SNAPSHOT",
    "MIN",
    "MAX",
    "SUM",
    "LEN",
    "REV",
    "UNIQ",
    "SORT",
    "DIFF",
    "INTER",
    "UNION"
};

char *g_cmd_help[CMD_NUM]={
    "BYE clear database and exit",
    "HELP display this help message",
    "LIST KEYS displays all keys in current state",
    "LIST ENTRIES displays all entries in current state",
    "LIST SNAPSHOTS displays all snapshots in the database",
    "GET <key> displays entry values",
    "DEL <key> deletes entry from current state",
    "PURGE <key> deletes entry from current state and snapshots",
    "SET <key> <value ...> sets entry values",
    "PUSH <key> <value ...> pushes values to the front",
    "APPEND <key> <value ...> appends values to the back",
    "PICK <key> <index> displays value at index",
    "PLUCK <key> <index> displays and removes value at index",
    "POP <key> displays and removes the front value",
    "DROP <id> deletes snapshot",
    "ROLLBACK <id> restores to snapshot and deletes newer snapshots",
    "CHECKOUT <id> replaces current state with a copy of snapshot",
    "SNAPSHOT saves the current state as a snapshot",
    "MIN <key> displays minimum value",
    "MAX <key> displays maximum value",
    "SUM <key> displays sum of values",
    "LEN <key> displays number of values",
    "REV <key> reverses order of values",
    "UNIQ <key> removes repeated adjacent values",
    "SORT <key> sorts values in ascending order",
    "DIFF <key> <key ...> displays set difference of values in keys",
    "INTER <key> <key ...> displays set intersection of values in keys",
    "UNION <key> <key ...> displays set union of values in keys"
};



void string_segmentation(char delimiter, char *string, int limit, string_segmentation_s * string_array)
{   
    int count = 1;
    char *pchar, **ptr;

    if ( NULL != string_array ) {
        memset(string_array, 0, sizeof(string_segmentation_s));
    }

    if(NULL == string || NULL == string_array || string[0] == '\0')
    {
        return;
    }

    if (0 == limit)
    {
        limit = 99999;
    }

    string_array->internal_buf = strdup(string);
    if(NULL == string_array->internal_buf)
    {
        return;
    }

    pchar = string;
    while('\0' != *pchar && (int)count < limit)
    {
        if (delimiter == *pchar)
        {
            count++;
        }
        pchar++;
    }
    string_array->strings = (char**)malloc(count*sizeof(char *));
    if(NULL == string_array->strings)
    {
        return;
    }
    string_array->len = count;

    ptr = string_array->strings;
    *ptr = string_array->internal_buf;
    pchar = string_array->internal_buf;
    while('\0' != *pchar && count > 1)
    {
        if (delimiter == *pchar)
        {
            ptr++;
            *ptr = pchar+1;
            *pchar = '\0';
            count--;
        }
        pchar++;
    }
}

void string_segmentation_free(string_segmentation_s *string_array)
{   
    if(NULL == string_array)
    {
        return;
    }
    if(string_array->internal_buf)
    {
        free(string_array->internal_buf);
    }
    if(string_array->strings)
    {
        free(string_array->strings);
    }
}


int g_snapshot_id=1;
extern char *gets(char *s);


void space_to_repeat(char *data)
{
    int new_len = strlen(data)-1;

    char *p=data;
    char *q;
    while(new_len>=0 && p[new_len]==' ')p[new_len--]='\0';
    while(*p!='\0' && *p == ' '){p=p+1;new_len--;}

    if(p != data)strcpy(data, p);

    p=strchr(p, ' ');
    while(p!=NULL){
        q=p+1;
        if(*q == ' '){
            while(*q!='\0' && *q==' ')q++;
            strcpy(p+1, q);
        }
        p=strchr(q, ' ');
    }

}

int cmd_get_str_from_file(char *cmd, int *cmd_len, FILE * fp)
{
    char  *ret=NULL;
    int str_len=0;

    if(feof(fp)){
        strcpy(cmd, "BYE");
        *cmd_len = 3;
        return RET_YES; 
    }

    ret = fgets(cmd, MAX_LINE, fp);
    if(ret == NULL){
        printf("ERROR: fail to read file\n");
        strcpy(cmd, "BYE");
        *cmd_len = 3;
        return RET_YES;     
    }

    str_len = strlen(cmd);
    while(cmd[str_len-1] == '\r'||cmd[str_len-1] == '\n'){
            cmd[str_len-1]='\0';
            str_len--;
    }
    space_to_repeat(cmd);
    *cmd_len = strlen(cmd);
    if(*cmd_len < 3 && *cmd_len >0){
        printf("Invalid command, enter the HELP command to view the help.\n");
        return RET_NO;
    }
    return RET_YES; 

}

int cmd_get_str_from_stdin(char *cmd, int *cmd_len)
{
    printf("> ");
    cmd[0]=0;
    gets(cmd);
    space_to_repeat(cmd);
    *cmd_len = strlen(cmd);
    if(*cmd_len < 3  && *cmd_len >0){
        printf("Invalid command, enter the HELP command to view the help.\n");
        return RET_NO;
    }

    return RET_YES; 
}

int cmd_get_id(string_segmentation_s *string_array)
{
    int i;
    int cmd_len;
    for(i=0;i<CMD_NUM;i++)
    {
        cmd_len = strlen(string_array->strings[0]); 
        if(memcmp(g_cmd_str[i], string_array->strings[0], cmd_len) == 0){
            if(memcmp("LIST", string_array->strings[0], 4) == 0 ){
                cmd_len = strlen(string_array->strings[1]);
                if(memcmp(g_cmd_str[i]+5, string_array->strings[1], cmd_len) != 0 ){
                    continue;
                }
            }
            return i;
        }
    }
    return i;
}

void cmd_help()
{
    int i;
    for(i=0;i<CMD_NUM;i++)
        printf("%s\n", g_cmd_help[i]);
}
void cmd_list_keys(entry *entry_h)
{
    entry * pnode;
    if (NULL == entry_h || entry_h == entry_h->prev){
        printf("no keys\n");
        return ;        
    }
    pnode= entry_h->prev;
    while (pnode != entry_h)
    {
        printf("%s\n", pnode->key);
        pnode = pnode ->prev;
    }

    return ;
}

void cmd_list_entries(entry *entry_h)
{
    int i=0;
    entry * pnode=NULL;
    if (NULL == entry_h || entry_h == entry_h->next){
        printf("no entries\n");
        return ;        
    }
    pnode= entry_h->next;
    while (pnode != entry_h)
    {
        printf("%s [", pnode->key);

        for(i=0;i< (int)pnode->length;i++){
            if(i!=0)printf(" ");
            printf("%d", pnode->values[i]);
        }
        printf("]\n");
        pnode = pnode ->next;
    }

    return ;
}

void cmd_list_snapshots(snapshot *snapshot_h)
{
    snapshot * pnode;
    if (NULL == snapshot_h || snapshot_h == snapshot_h->next){
        printf("no snapshots\n");
        return ;        
    }
    pnode= snapshot_h->next;
    while (pnode != snapshot_h)
    {
        printf("%d\n", pnode->id);
        pnode = pnode ->next;
    }

    return ;
}

void cmd_get(entry * entry_h, char *key)
{


    int i=0;
    entry *p = NULL;
    p = entry_find_node(entry_h, key);
    if(p == NULL){
        printf("no such key\n");
        return ;
    }

    printf("[");
    for(i=0;i< (int)p->length;i++){
        if(i!=0)printf(" ");
        printf("%d", p->values[i]);
    }
    printf("]\n");
    return ;
}

void cmd_del(entry * entry_h, char *key, int isprintf)
{

    entry *p = entry_find_node(entry_h, key);
    if(p == NULL){
        if(isprintf == RET_YES)
            printf("no such key\n");
        return ;
    }

    entry_delete_node(p);
    if(isprintf == RET_YES)
        printf("ok\n"); 
    return ;
}

void cmd_purge(entry * entry_h, snapshot *snapshot_h, char *key)
{
    entry temp_entry_h;

    if(entry_h != NULL)
        cmd_del(entry_h, key, RET_NO);

    if(snapshot_h != NULL){
        entry_add_head(&temp_entry_h, snapshot_h->entries);
        cmd_del(&temp_entry_h, key, RET_NO);
        snapshot_h->entries = entry_pick_off_head(&temp_entry_h);       
    }

    printf("ok\n");
    return ;
}
//Returns a node pointer to the newly added or modified
entry *cmd_set(entry *entry_h, char *key, char **values, int len)
{

    int i=0;
    entry *p = NULL;


    if(key == NULL || values == NULL ){
        printf("invalid parameter\n");
        return NULL;
    }

    p=entry_find_node(entry_h, key);
    if(p == NULL){
        p = entry_create_node(key, values, len);
        entry_insert_node(entry_h, p);
    }else{
        p->length=len;
        free(p->values);
        p->values = NULL;
        if(len>0){
            p->values=(int *)malloc(sizeof(int) * len);
            for(i=0;i<len;i++)
                p->values[i]=atoi(values[i]);           
        }

    }
    printf("ok\n"); 
    return p;       
}
entry *cmd_push(entry *entry_h, char *key, char **values, int len)
{

    int i;
    entry *p = NULL;


    if(key == NULL || values == NULL ){
        printf("invalid parameter\n");
        return NULL;
    }

    p=entry_find_node(entry_h, key);
    if(p == NULL){
        p = entry_create_node(key, values, len);
        entry_insert_node(entry_h, p);
    }else{
        int new_len = len+p->length;
        if(new_len > 0){
            int *t_v=(int *)malloc(sizeof(int)*(new_len));
            for(i=0;i<len;i++)
                t_v[i]=atoi(values[i]); 
            memcpy(t_v+len, p->values, sizeof(int)*p->length);

            p->length=new_len;
            free(p->values);
            p->values = t_v;                            
        }else{
            p->values = NULL;
        }



    }
    printf("ok\n"); 
    return p;       
}

entry *cmd_append(entry *entry_h, char *key, char **values, int len)
{

    int i;
    entry *p = NULL;


    if(key == NULL || values == NULL ){
        printf("invalid parameter\n");
        return NULL;
    }

    p=entry_find_node(entry_h, key);
    if(p == NULL){
        p = entry_create_node(key, values, len);
        entry_insert_node(entry_h, p);
    }else{
        int new_len = len+p->length;
        if(new_len > 0){
            int *t_v=(int *)malloc(sizeof(int)*(new_len));
            memcpy(t_v, p->values, sizeof(int)*p->length);
            for(i=p->length;i<new_len;i++)
                t_v[i]=atoi(values[i-p->length]);
            p->length = new_len;
            free(p->values);
            p->values = t_v;            
        }else{
            p->values = NULL;
        }

    }
    printf("ok\n"); 
    return p;       
}

entry *cmd_pick(entry *entry_h, char *key, char *values, int len)
{

    int i;
    entry *p = NULL;


    if(key == NULL || values == NULL ){
        printf("Invalid parameter, enter the HELP command to view the help.\n");
        return NULL;
    }

    if(len != 1){
        printf("Invalid parameter, enter the HELP command to view the help.\n");        
        return NULL;
    }

    p=entry_find_node(entry_h, key);
    if(p == NULL){
        printf("no such key\n");
    }else{
        i=atoi(values);
        if(i<1 || i> (int)p->length)
            printf("index out of range\n");
        else
            printf("%d\n", p->values[i-1]);
    }
    return p;       
}

entry *cmd_pluck(entry *entry_h, char *key, char *values, int len)
{

    int i;
    entry *p = NULL;


    if(key == NULL || values == NULL ){
        printf("Invalid parameter, enter the HELP command to view the help.\n");
        return NULL;
    }

    if(len != 1){
        printf("Invalid parameter, enter the HELP command to view the help.\n");        
        return NULL;
    }

    p=entry_find_node(entry_h, key);
    if(p == NULL){
        printf("no such key\n");
    }else{
        i=atoi(values);
        if(i<1 || i> (int)p->length)
            printf("index out of range\n");
        else{
            printf("%d\n", p->values[i-1]);
            memcpy(p->values+i-1, p->values+i, (p->length-i)*sizeof(int));
            p->length--;        
        }

    }
    return p;       
}
entry *cmd_pop(entry *entry_h, char *key)
{

    entry *p = NULL;


    if(key == NULL  ){
        printf("Invalid parameter, enter the HELP command to view the help.\n");
        return NULL;
    }

    p=entry_find_node(entry_h, key);
    if(p == NULL){
        printf("no such key\n");
    }else{
        if(p->length > 0){
            printf("%d\n", p->values[0]);
            p->length--;
            memcpy(p->values, p->values+1, sizeof(int)*p->length);
        }else{
            printf("nil\n");
        }
    }
    return p;       
}

snapshot *cmd_drop(snapshot *snapshot_h, int id)
{
    snapshot *p = NULL;

    p=snapshot_find_node(snapshot_h, id);
    if(p == NULL){
        printf("no such snapshot\n");
    }else{
        snapshot_delete_node(p);
        printf("ok\n");
    }
    return p;       
}
snapshot *cmd_rollback(snapshot *snapshot_h, int id)
{
    snapshot *p = NULL;

    p=snapshot_find_node(snapshot_h, id);
    if(p == NULL){
        printf("no such snapshot\n");
    }else{
        snapshot_delete_more_than_ID(snapshot_h, id);
        printf("ok\n");
    }
    return p;
}

snapshot *cmd_checkout(snapshot *snapshot_h, int id)
{
    snapshot *p = NULL;
    entry temp_head;
    p=snapshot_find_node(snapshot_h, id);
    cur_snapshot_h = p;
    if(p == NULL){
        printf("no such snapshot\n");
    }else{
        entry_delete_list(&cur_entry_h);

        entry_head_init(&temp_head);
        entry_add_head(&temp_head, p->entries);

        entry_copy(&cur_entry_h, &temp_head);

        entry_pick_off_head(&temp_head);
        printf("ok\n");
    }
    return p;
}

snapshot *cmd_snapshot(snapshot *snapshot_h)
{
    snapshot *p = NULL;
    entry temp_head;


    p=snapshot_create_node(g_snapshot_id);
    cur_snapshot_h = p;
    if(p == NULL){
        printf("no such snapshot\n");
    }else{
        g_snapshot_id++;        

        entry_head_init(&temp_head);
        entry_copy(&temp_head, &cur_entry_h);
        p->entries = entry_pick_off_head(&temp_head);

        snapshot_insert_node(snapshot_h, p);
        printf("saved as snapshot %d\n", p->id);

    }
    return p;
}

void cmd_min(entry * entry_h, char *key)
{
    int i;
    int min;
    entry *p = entry_find_node(entry_h, key);

    if(p == NULL){
        printf("no such key\n");
        return ;
    }

    if(p->length > 0){
        min = p->values[0];
        for(i=1;i< (int)p->length;i++){
            if(min>p->values[i])min = p->values[i];
        }
        printf("%d\n", min);    
    }else{
        printf("key values number is 0\n");
    }

    return ;
}

void cmd_max(entry * entry_h, char *key)
{
    int i;
    int max;
    entry *p = entry_find_node(entry_h, key);

    if(p == NULL){
        printf("no such key\n");
        return ;
    }

    if(p->length > 0){
        max = p->values[0];
        for(i=1;i < (int)p->length;i++){
            if(max < p->values[i])max = p->values[i];
        }
        printf("%d\n", max);    
    }else{
        printf("key values number is 0\n");
    }

    return ;
}

void cmd_sum(entry * entry_h, char *key)
{
    int i=0;
    int sum=0;
    entry *p = entry_find_node(entry_h, key);

    if(p == NULL){
        printf("no such key\n");
        return ;
    }

    for(i=0;i < (int)p->length;i++){
        sum=sum+p->values[i];
    }
    printf("%d\n", sum);

    return ;
}


void cmd_len(entry * entry_h, char *key)
{


    entry *p = entry_find_node(entry_h, key);

    if(p == NULL){
        printf("no such key\n");
        return ;
    }

    printf("%d\n", (int)(p->length));
    return ;
}

void cmd_rev(entry * entry_h, char *key)
{
    int i;
    int len;
    entry *p = entry_find_node(entry_h, key);
    int t;

    if(p == NULL){
        printf("no such key\n");
        return ;
    }else{
        len = p->length;
        for(i=0;i<len/2;i++){
            t=p->values[i];
            p->values[i]=p->values[len-i-1];
            p->values[len-i-1]=t;
        }
        printf("ok\n");
    }

    return ;
}

int original_order_to_repeat(int *data, int len)
{
    int i,j;
/*
    for(i=0;i<*len;i++){
        for(j=i+1;j<*len;j++){
            if(data[i] == data[j] ){
                    memcpy((void *)(*len+j), (void *)(*len+j+1), sizeof(int)* (*len-j-1));
                    *len--;
            }
        }
    }*/


    int t_len=0;
    for(i=0;i<len;i++){
        for(j=0;j<t_len;j++){
            if(data[i] == data[j] ){
                break;
            }
        }
        if(j==t_len){
            data[t_len++]=data[i];
        }
    }
    return t_len;

}


void cmd_uniq(entry * entry_h, char *key)
{

    entry *p = entry_find_node(entry_h, key);

    if(p == NULL){
        printf("no such key\n");
        return ;
    }else{
        p->length = original_order_to_repeat(p->values, p->length);
        printf("ok\n");
    }

    return ;
}


int cmp_asc(const void *a, const void *b)
{
    return *(int *)a>*(int *)b;
}

void cmd_sort(entry * entry_h, char *key)
{

    entry *p = entry_find_node(entry_h, key);

    if(p == NULL){
        printf("no such key\n");
        return ;
    }else{

        qsort(p->values, p->length, sizeof(int), cmp_asc);
        printf("ok\n");
    }

    return ;
}

int bi_search(int data[], const int x, int beg, int last)  
{  
    int mid;
    if (beg > last)  
    {  
        return RET_YES;  
    }  

    while(beg <= last)  
    {  
        mid = (beg + last) / 2;  
        if (x == data[mid] )  
        {  
            return RET_YES;  
        }  
        else if (data[mid] < x)  
        {  
            beg = mid + 1;  
        }  
        else if (data[mid] > x)  
        {  
            last = mid - 1;  
        }  
    }  
    return RET_NO;  
}

int order_search(int data[], const int x, int len)  
{  
    int i;
    for(i=0;i<len;i++){
        if(data[i] == x)return RET_YES;
    } 
    return RET_NO;
}

void cmd_diff(entry *entry_h, char **keys, int keys_num)
{
    entry *k;
    int i,j;
    int *A;
    int A_len=0;

    int *B;
    int B_len=0;

    int new_len =0;
    if(entry_h == NULL || keys == NULL)return ;


    k=entry_find_node(entry_h, keys[0]);
    A_len = k->length;
    A=(int *)malloc(sizeof(int)*A_len); 
    memcpy(A, k->values, sizeof(int)*A_len);

    for(i=1;i<keys_num; i++)
    {
        k=entry_find_node(entry_h, keys[i]);
        if(k == NULL)continue;
        B=k->values;
        B_len = k->length;
        new_len =0;
        for(j=0;j<A_len;j++){
            if(order_search(B, A[j], B_len) == RET_YES){
                continue;
            }
            A[new_len++]=A[j];
        }
        A_len = new_len;
    }

    for(i=0;i<A_len; i++){
        if(i!=0)printf(" ");
        printf("%d", A[i]);
    }
    free(A);
    printf("\n");

}


int qsort_to_repeat(int *data, int len)
{
    int new_len = 0;
    int i;

    qsort((void *)data, len, sizeof(int), cmp_asc);


    for(i=1;i<len;i++){
        if(data[new_len]!=data[i]){
            new_len++;
            data[new_len]=data[i];
        }
    }
    return new_len+1;
}

void bubble_sort(int a[], int n)
{
    int i, j, temp;
    int k=0;
    for (j = 0; j < n - 1; j++){
        k=0;
        for (i = 0; i < n - 1 - j; i++)
        {
            if(a[i] > a[i + 1])
            {
                k=1;
                temp = a[i];
                a[i] = a[i + 1];
                a[i + 1] = temp;
            }
        }  
        if(k==0)break;  
    }
}

void cmd_inter(entry *entry_h, char **keys, int keys_num)
{
    entry **k;
    int i;
    int *buff;
    int buff_len=0;
    int offset=0;
    int *t_buff;
    int t_buff_len;

    if(entry_h == NULL || keys == NULL)return ;

    k=(entry **)malloc(sizeof(entry *) * keys_num);

    for(i=0;i<keys_num; i++)
    {
        k[i]=entry_find_node(entry_h, keys[i]);
        if(k[i] == NULL){
            free(k);
            return;
        }
        if(k[i]->length == 0){
            free(k);
            return;
        }
        buff_len += k[i]->length;
    }

    buff=(int *)malloc(sizeof(int)*buff_len);


    for(i=0; i<keys_num; i++){
        t_buff_len = k[i]->length;
        t_buff = (int *)malloc(sizeof(int)*t_buff_len);
        memcpy(t_buff, k[i]->values, sizeof(int)*t_buff_len);
        t_buff_len = qsort_to_repeat(t_buff, t_buff_len);
        memcpy((void *)buff+offset*sizeof(int), t_buff, sizeof(int)*t_buff_len);
        free(t_buff);
        t_buff = NULL;
        offset = offset +t_buff_len;
    }

    bubble_sort(buff, offset);
    //qsort(buff, offset, sizeof(int), cmp_asc);


    int t_num=0;
    int t_data=buff[0];
    for(i=0;i<offset; i++){
        if(t_data == buff[i]){
            t_num++;
        }else{
            t_data=buff[i];
            t_num =1;           
        }

        if(t_num == keys_num){
            printf("%d ", t_data);

        }


    }


    free(buff);
    free(k);
    printf("\n");

}

void cmd_union(entry *entry_h, char **keys, int keys_num)
{
    entry **k;
    int i;
    int *buff;
    int buff_len=0;

    if(entry_h == NULL || keys == NULL)return ;

    k=(entry **)malloc(sizeof(entry *) * keys_num);

    for(i=0;i<keys_num; i++)
    {
        k[i]=entry_find_node(entry_h, keys[i]);
        if(k[i] == NULL )continue;
        buff_len += k[i]->length;
    }

    buff=(int *)malloc(sizeof(int)*buff_len);

    int offset=0;
    for(i=0; i<keys_num; i++){
        if(k[i] == NULL)continue;
        memcpy(buff+offset, k[i]->values, sizeof(int)*k[i]->length);
        offset = offset +k[i]->length;
    }

    buff_len = original_order_to_repeat(buff, buff_len);

    for(i=0;i<buff_len; i++){
        if(i!=0)printf(" ");
        printf("%d", buff[i]);
    }   
    printf("\n");

    free(buff);
    free(k);
}

void cmd_dispatch(int cmd_id, string_segmentation_s *string_array)
{
    switch(cmd_id){
        //CMD_BYE:
        case CMD_HELP:
            if(string_array->len!=1){
                printf("Invalid parameter, enter the HELP command to view the help.\n");
                break;
            }
            cmd_help();
            break;
        case CMD_LIST_KEYS:
            cmd_list_keys(&cur_entry_h);
            break;
        case CMD_LIST_ENTRIES:
            cmd_list_entries(&cur_entry_h);
            break;
        case CMD_LIST_SNAPSHOTS:
            cmd_list_snapshots(&g_snapshot_h);
            break;
        case CMD_GET:
            if(string_array->len!=2){
                printf("Invalid parameter, enter the HELP command to view the help.\n");
                break;
            }
            cmd_get(&cur_entry_h, string_array->strings[1]);
            break;
        case CMD_DEL:
            if(string_array->len!=2){
                printf("Invalid parameter, enter the HELP command to view the help.\n");
                break;
            }
            cmd_del(&cur_entry_h, string_array->strings[1], RET_YES);
            break;          
        case CMD_PURGE:
            if(string_array->len!=2){
                printf("Invalid parameter, enter the HELP command to view the help.\n");
                break;
            }
            cmd_purge(&cur_entry_h, cur_snapshot_h, string_array->strings[1]);
            break;
        case CMD_SET:
            if(string_array->len < 2){
                printf("Invalid parameter, enter the HELP command to view the help.\n");
                break;
            }
            cmd_set(&cur_entry_h, string_array->strings[1], string_array->strings+2, string_array->len-2);
            break;
        case CMD_PUSH:
            if(string_array->len!=2){
                printf("Invalid parameter, enter the HELP command to view the help.\n");
                break;
            }
            cmd_push(&cur_entry_h, string_array->strings[1], string_array->strings+2, string_array->len-2);
            break;
        case CMD_APPEND:
            if(string_array->len!=2){
                printf("Invalid parameter, enter the HELP command to view the help.\n");
                break;
            }
            cmd_append(&cur_entry_h, string_array->strings[1], string_array->strings+2, string_array->len-2);
            break;
        case CMD_PICK:
            if(string_array->len!=3){
                printf("Invalid parameter, enter the HELP command to view the help.\n");
                break;
            }
            cmd_pick(&cur_entry_h, string_array->strings[1], string_array->strings[2], string_array->len-2);
            break;
        case CMD_PLUCK:
            if(string_array->len!=3){
                printf("Invalid parameter, enter the HELP command to view the help.\n");
                break;
            }
            cmd_pluck(&cur_entry_h, string_array->strings[1], string_array->strings[2], string_array->len-2);
            break;          
        case CMD_POP:
            if(string_array->len!=2){
                printf("Invalid parameter, enter the HELP command to view the help.\n");
                break;
            }
            cmd_pop(&cur_entry_h, string_array->strings[1]);
            break;
        case CMD_DROP:
            if(string_array->len!=2){
                printf("Invalid parameter, enter the HELP command to view the help.\n");
                break;
            }
            cmd_drop(&g_snapshot_h, atoi(string_array->strings[1]));
            break;
        case CMD_ROLLBACK:
            if(string_array->len!=2){
                printf("Invalid parameter, enter the HELP command to view the help.\n");
                break;
            }
            cmd_rollback(&g_snapshot_h, atoi(string_array->strings[1]));
            break;
        case CMD_CHECKOUT:
            if(string_array->len!=2){
                printf("Invalid parameter, enter the HELP command to view the help.\n");
                break;
            }
            cmd_checkout(&g_snapshot_h, atoi(string_array->strings[1]));
            break;
        case CMD_SNAPSHOT:
            if(string_array->len!=1){
                printf("Invalid parameter, enter the HELP command to view the help.\n");
                break;
            }
            cmd_snapshot(&g_snapshot_h);
            break;
        case CMD_MIN:
            if(string_array->len!=2){
                printf("Invalid parameter, enter the HELP command to view the help.\n");
                break;
            }
            cmd_min(&cur_entry_h, string_array->strings[1]);
            break;      
        case CMD_MAX:
            if(string_array->len!=2){
                printf("Invalid parameter, enter the HELP command to view the help.\n");
                break;
            }
            cmd_max(&cur_entry_h, string_array->strings[1]);
            break;
        case CMD_SUM:
            if(string_array->len!=2){
                printf("Invalid parameter, enter the HELP command to view the help.\n");
                break;
            }
            cmd_sum(&cur_entry_h, string_array->strings[1]);
            break;
        case CMD_LEN:
            if(string_array->len!=2){
                printf("Invalid parameter, enter the HELP command to view the help.\n");
                break;
            }
            cmd_len(&cur_entry_h, string_array->strings[1]);
            break;
        case CMD_REV:
            if(string_array->len!=2){
                printf("Invalid parameter, enter the HELP command to view the help.\n");
                break;
            }
            cmd_rev(&cur_entry_h, string_array->strings[1]);
            break;
        case CMD_UNIQ:
            if(string_array->len!=2){
                printf("Invalid parameter, enter the HELP command to view the help.\n");
                break;
            }
            cmd_uniq(&cur_entry_h, string_array->strings[1]);
            break;
        case CMD_SORT:
            if(string_array->len!=2){
                printf("Invalid parameter, enter the HELP command to view the help.\n");
                break;
            }
            cmd_sort(&cur_entry_h, string_array->strings[1]);
            break;
        case CMD_DIFF:
            if(string_array->len < 2){
                printf("Invalid parameter, enter the HELP command to view the help.\n");
                break;
            }
            cmd_diff(&cur_entry_h, string_array->strings+1, string_array->len-1);
            break;
        case CMD_INTER:
            if(string_array->len < 2){
                printf("Invalid parameter, enter the HELP command to view the help.\n");
                break;
            }
            cmd_inter(&cur_entry_h, string_array->strings+1, string_array->len-1);
            break;
        case CMD_UNION:
            if(string_array->len < 2){
                printf("Invalid parameter, enter the HELP command to view the help.\n");
                break;
            }
            cmd_union(&cur_entry_h, string_array->strings+1, string_array->len-1);
            break;
        default:
            break;
        //CMD_NUM
    };

    return ;

}

snapshot_list.h

#ifndef SNAPSHOT_LIST_H
#define SNAPSHOT_LIST_H

extern void entry_head_init(entry *head);
extern entry * entry_create_node(char *key, char **values, int len);
extern entry *entry_find_node(entry *head, char *key);
extern entry *entry_insert_node(entry *head, entry *pnode);
extern void entry_delete_node(entry *pnode);
extern void entry_delete_list(entry *head);
extern entry *entry_add_head(entry *new_head, entry *old_head);
extern entry *entry_pick_off_head(entry *old_head);
extern entry *entry_copy(entry *new_head, entry *old_head);


extern void snapshot_head_init(snapshot *head);
extern snapshot *snapshot_create_node(int id);
extern snapshot *snapshot_find_node(snapshot *head, int id);
extern snapshot *snapshot_insert_node(snapshot *head, snapshot *pnode);
extern void snapshot_delete_node(snapshot *pnode);
extern void snapshot_delete_list(snapshot *head);
extern void snapshot_delete_more_than_ID(snapshot *head, int id);


#endif

snapshot_list.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "snapshot.h"
#include "snapshot_list.h"



void entry_print_order(entry *head)
{
    entry * pnode;
    if (NULL == head) return;
    pnode= head->next;
    while (pnode != head)
    {
        printf("%s\n", pnode->key);
        pnode = pnode->next;
    }

}

void entry_print_rever(entry *head)
{
    entry * pnode;
    if (NULL == head) return;
    pnode= head->next;
    while (pnode != head)
    {
        printf("%s\n", pnode->key);
        pnode = pnode->next;
    }

}
void entry_head_init(entry *head) 
{
    head->key[0]='\0';
    head->next=head;
    head->prev=head;
}

entry * entry_create_node(char *key, char **values, int len)
{
    int i;
    entry * p = (entry *)malloc(sizeof(entry));
    strcpy(p->key, key);
    p->length=len;
    if(len>0){
        p->values=(int *)malloc(sizeof(int) * len);
        for(i=0;i<len;i++)
            p->values[i]=atoi(values[i]);       
    }else{
        p->values=NULL;
    }

    p->next=p;
    p->prev=p;
    return p;
}


entry *entry_find_node(entry *head, char *key) 
{
    entry * pnode = head->next;

    while (pnode != head && pnode->key[0] != '\0' && strcmp(pnode->key, key) != 0)
    {
        pnode = pnode->next;
    }
    if (pnode == head)  return NULL; 
    return pnode;
}

entry *entry_insert_node(entry *head, entry *pnode)
{
    entry *q;
    if(head == NULL || pnode == NULL)return NULL;

    q=head->prev;

    q->next=pnode;
    pnode->next=head;

    head->prev=pnode;
    pnode->prev=q;

    return head;
}

void entry_delete_node(entry *pnode) 
{
    if (NULL == pnode) return; 
    pnode->prev->next=pnode->next;
    pnode->next->prev=pnode->prev;
    if(pnode->values)
        free(pnode->values);
    if(pnode)
        free(pnode); 
    return ;
}

void entry_delete_list(entry *head)
{
    entry * pnode = head->next;
    entry * ptmp;
    if (NULL == head) return; 

    while (pnode != head)
    {
        ptmp = pnode;
        pnode= pnode->next;
        if(ptmp->values)
            free(ptmp->values);
        if(ptmp)
            free(ptmp);
    }
    entry_head_init(head);
}

entry *entry_add_head(entry *new_head, entry *old_head)
{
     if(new_head == NULL || old_head == NULL)return NULL;

     entry_head_init(new_head);
     entry_insert_node(old_head, new_head);

     return new_head;
}

entry *entry_pick_off_head(entry *old_head)
{

     entry *new_head = old_head->next;
     entry *qnode = old_head->prev;

     new_head->prev=qnode;
     qnode->next=new_head;

     return new_head;
}

entry *entry_copy(entry *new_head, entry *old_head)
{

    entry * pnode;
    entry * ptmp;
    if (NULL == new_head || NULL == old_head) return NULL; 

    pnode = old_head->next;
    entry_head_init(new_head);

    while (pnode != old_head)
    {
        ptmp=(entry *)malloc(sizeof(entry));
        memcpy((void *)ptmp, (void *)pnode, sizeof(entry));
        ptmp->values = (int *)malloc(sizeof(int)*pnode->length);
        memcpy(ptmp->values, pnode->values, sizeof(int)*pnode->length);
        entry_insert_node(new_head, ptmp);
        pnode=pnode->next;
    }
    return new_head;
}


void snapshot_head_init(snapshot *head) 
{
    head->next=head;
    head->prev=head;
}

snapshot *snapshot_create_node(int id)
{
    snapshot *p = (snapshot *)malloc(sizeof(snapshot));
    p->id=id;
    p->entries=NULL;
    p->next=p;
    p->prev=p;
    return p;
}


snapshot *snapshot_find_node(snapshot *head, int id) 
{
    snapshot *pnode = head->next;
    while (pnode != head && pnode->id != id)
    {
        pnode = pnode->next;
    } 
    if (pnode == head)  return NULL; 
    return pnode;
}


snapshot *snapshot_insert_node(snapshot *head, snapshot *pnode)
{ 
     head->prev->next = pnode;
     pnode->next = head;

     pnode->prev = head->prev;
     head->prev = pnode;

     return head;
}

void snapshot_delete_node(snapshot *pnode) 
{
    entry entry_head;

    if (NULL == pnode) return; 
    pnode->prev->next=pnode->next;
    pnode->next->prev=pnode->prev;

    entry_add_head(&entry_head, pnode->entries);
    entry_delete_list(&entry_head);

    free(pnode); 
    return ;
}

void snapshot_delete_list(snapshot *head)
{
    snapshot * pnode = head->next;
    snapshot * ptmp;
    entry entry_head;

    if (NULL == head) return; 

    while (pnode != head)
    {

        ptmp = pnode;
        pnode=pnode->next;
        entry_add_head(&entry_head, ptmp->entries);
        entry_delete_list(&entry_head);
        if(ptmp)
            free(ptmp);
        ptmp = NULL;
    }
    snapshot_head_init(head);
}


void snapshot_delete_more_than_ID(snapshot *head, int id)
{
    snapshot * pnode = head->next;
    snapshot * ptmp;

    if (NULL == head) return; 

    while (pnode != head)
    {
        ptmp = pnode;
        pnode=pnode->next;  
        if(ptmp->id > id){
            snapshot_delete_node(ptmp);
            ptmp = NULL;
        }
    }
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Brickie-liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值