开启 Redis 研究及应用之旅
回顾2010年,NOSQL是云计算中一个主角,备受各界关注。一时间相关产品也蜂拥而来,非常火爆。比如,Redis,Tokyo Cabinet,Cassandra,Voldemort,MongoDB,Dynomite,HBase,CouchDB,Hypertable,Riak,Tin,Flare,Lightcloud,KiokuDB,Scalaris,Kai,ThruDB等等。 当然,不光上面罗列的这些了,还有国内由吴朱华开发的yuntable。感兴趣的朋友可以从yuntable的官网http://code.google.com/p/yuntable/获得更多的信息。
Redis是NOSQL中最闪耀的名星之一。其性能非常优越,构架简单,便于管理和维护。同时,代码量非常少,也便于学习、研究。适逢春节,笔者将对其进行各层次深入分析和研究。关于代码量,请看以下简单统计:
(1)代码版本:redis-2.2.0-rc3
(2)统计以下目录下的*.[ch]文件:
redis-2.2.0-rc3/src
redis-2.2.0-rc3/deps/linenoise
redis-2.2.0-rc3/deps/hiredis
(3)有效代码行数统计结果,如下:
hacker@earch> cd ~/redis-2.2.0-rc3
hacker@earch> cat src/*.[ch] deps/*/*.[ch] | grep -v -E "^((( |/t|//)+/*)|((| |/t)+$)|/*|//)" | wc -l 19863
(4)grep模式匹配结果,如下:
hacker@earch> cat src/*.[ch] deps/*/*.[ch] | grep -v -E "^((( |/t|//)+/*)|((| |/t)+$)|/*|//)" | nl -ba
1 #include <stdlib.h> 2 #include "adlist.h" 3 #include "zmalloc.h" 4 list *listCreate(void) 5 { 6 struct list *list; 7 if ((list = zmalloc(sizeof(*list))) == NULL) 8 return NULL; 9 list->head = list->tail = NULL; 10 list->len = 0; 11 list->dup = NULL; 12 list->free = NULL; 13 list->match = NULL; 14 return list; 15 } 16 void listRelease(list *list) 17 { 18 unsigned int len; 19 listNode *current, *next; 20 current = list->head; 21 len = list->len; 22 while(len--) { 23 next = current->next; 24 if (list->free) list->free(current->value); 25 zfree(current); 26 current = next; 27 } 28 zfree(list); 29 } 30 list *listAddNodeHead(list *list, void *value) ...
19759 char *linenoise(const char *prompt) { 19760 char buf[LINENOISE_MAX_LINE]; 19761 int count; 19762 if (isUnsupportedTerm()) { 19763 size_t len; 19764 printf("%s",prompt); 19765 fflush(stdout); 19766 if (fgets(buf,LINENOISE_MAX_LINE,stdin) == NULL) return NULL; 19767 len = strlen(buf); 19768 while(len && (buf[len-1] == '/n' || buf[len-1] == '/r')) { 19769 len--; 19770 buf[len] = '/0'; 19771 } 19772 return strdup(buf); 19773 } else { 19774 count = linenoiseRaw(buf,LINENOISE_MAX_LINE,prompt); 19775 if (count == -1) return NULL; 19776 return strdup(buf); 19777 } 19778 } 19779 void linenoiseSetCompletionCallback(linenoiseCompletionCallback *fn) { 19780 completionCallback = fn; 19781 } 19782 void linenoiseAddCompletion(linenoiseCompletions *lc, char *str) { 19783 size_t len = strlen(str); 19784 char *copy = malloc(len+1); 19785 memcpy(copy,str,len+1); 19786 lc->cvec = realloc(lc->cvec,sizeof(char*)*(lc->len+1)); 19787 lc->cvec[lc->len++] = copy; 19788 } 19789 int linenoiseHistoryAdd(const char *line) { 19790 char *linecopy; 19791 if (history_max_len == 0) return 0; 19792 if (history == NULL) { 19793 history = malloc(sizeof(char*)*history_max_len); 19794 if (history == NULL) return 0; 19795 memset(history,0,(sizeof(char*)*history_max_len)); 19796 } 19797 linecopy = strdup(line); 19798 if (!linecopy) return 0; 19799 if (history_len == history_max_len) { 19800 free(history[0]); 19801 memmove(history,history+1,sizeof(char*)*(history_max_len-1)); 19802 history_len--; 19803 } 19804 history[history_len] = linecopy; 19805 history_len++; 19806 return 1; 19807 } 19808 int linenoiseHistorySetMaxLen(int len) { 19809 char **new; 19810 if (len < 1) return 0; 19811 if (history) { 19812 int tocopy = history_len; 19813 new = malloc(sizeof(char*)*len); 19814 if (new == NULL) return 0; 19815 if (len < tocopy) tocopy = len; 19816 memcpy(new,history+(history_max_len-tocopy), sizeof(char*)*tocopy); 19817 free(history); 19818 history = new; 19819 } 19820 history_max_len = len; 19821 if (history_len > history_max_len) 19822 history_len = history_max_len; 19823 return 1; 19824 } 19825 int linenoiseHistorySave(char *filename) { 19826 FILE *fp = fopen(filename,"w"); 19827 int j; 19828 if (fp == NULL) return -1; 19829 for (j = 0; j < history_len; j++) 19830 fprintf(fp,"%s/n",history[j]); 19831 fclose(fp); 19832 return 0; 19833 } 19834 int linenoiseHistoryLoad(char *filename) { 19835 FILE *fp = fopen(filename,"r"); 19836 char buf[LINENOISE_MAX_LINE]; 19837 if (fp == NULL) return -1; 19838 while (fgets(buf,LINENOISE_MAX_LINE,fp) != NULL) { 19839 char *p; 19840 p = strchr(buf,'/r'); 19841 if (!p) p = strchr(buf,'/n'); 19842 if (p) *p = '/0'; 19843 linenoiseHistoryAdd(buf); 19844 } 19845 fclose(fp); 19846 return 0; 19847 } 19848 #ifndef __LINENOISE_H 19849 #define __LINENOISE_H 19850 typedef struct linenoiseCompletions { 19851 size_t len; 19852 char **cvec; 19853 } linenoiseCompletions; 19854 typedef void(linenoiseCompletionCallback)(const char *, linenoiseCompletions *); 19855 void linenoiseSetCompletionCallback(linenoiseCompletionCallback *); 19856 void linenoiseAddCompletion(linenoiseCompletions *, char *); 19857 char *linenoise(const char *prompt); 19858 int linenoiseHistoryAdd(const char *line); 19859 int linenoiseHistorySetMaxLen(int len); 19860 int linenoiseHistorySave(char *filename); 19861 int linenoiseHistoryLoad(char *filename); 19862 void linenoiseClearScreen(void); 19863 #endif /* __LINENOISE_H */