-
Notifications
You must be signed in to change notification settings - Fork 58
/
vedis_shell.c
194 lines (183 loc) · 5.74 KB
/
vedis_shell.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/*
* Compile this file together with the vedis engine source code to generate
* the desired executable. For example:
* gcc -W -Wall -O6 vedis_shell.c vedis.c -o vedis_shell
*/
/*
* The Vedis shell is a simple standalone program which let you execute
* built-in Vedis commands from your command line interface (CLI).
*
* Introduction to the Command Execution Interfaces (CEI):
*
* Structured data storage is presented to clients via the command execution interface.
* Basically, you execute one or more commands ala Redis (i.e. SET key value; HSET ds key value, GET key)
* via [vedis_exec()] and you extract the execution result (The return value of the command) via
* [vedis_exec_result()]. You could also register foreign commands via [vedis_register_commmand()].
* You may also be tempted by installing a command consumer callback in case you
* want to invoke multiple commands (pipelined request) in a single [vedis_exec()] call rather
* than calling [vedis_exec_result()] which return only the execution result of the last executed
* command.
*
* For an introduction to the Vedis C/C++ interface, please refer to:
* http://vedis.symisc.net/api_intro.html
* For the full C/C++ API reference guide, please refer to:
* http://vedis.symisc.net/c_api.html
* Vedis in 5 Minutes or Less:
* http://vedis.symisc.net/intro.html
* Built-in Vedis Commands:
* http://vedis.symisc.net/commands.html
*/
/* $SymiscID: vedis_shell.c v1.0.4 Linux 2013-09-15 02:22 stable <[email protected]> $ */
/* Make sure you have the latest release of the Vedis engine
* from:
* http://vedis.symisc.net/downloads.html
*/
#include <stdio.h>
#include <stdlib.h>
/* Make sure this header file is available.*/
#include "vedis.h"
/*
* Display an error message and exit.
*/
static void Fatal(const char *zMsg)
{
puts(zMsg);
/* Shutdown the library */
vedis_lib_shutdown();
/* Exit immediately */
exit(0);
}
/*
* Banner.
*/
static const char zBanner[] = {
"============================================================\n"
" Simple Vedis Shell \n"
" http://vedis.symisc.net/\n"
" Enter one or more Vedis commands. \n"
" \n"
" Type 'CMD_LIST' for a list of built-in Vedis commands. \n"
" \n"
" Enter a blank line to exit the shell \n"
"============================================================\n"
};
/*
* atexit() callback. Shutdown the Vedis library.
*/
void vedis_exit(void)
{
vedis_lib_shutdown();
}
#include <ctype.h>
/*
* Return true only if we are dealing with a blank line.
*/
int isBlank(const char *zIn,unsigned int nByte)
{
const char *zEnd = &zIn[nByte];
while( zIn < zEnd && (isspace(zIn[0])) ){
/* Advance the cursor */
zIn++;
}
return (zIn[0] == 0 || zIn >= zEnd) ? 1 : 0;
}
/* Forward declaration */
struct array_rend
{
int is_first;
int cnt;
};
static int array_render(vedis_value *pEntry,void *pUserdata);
/*
* Command result consumer callback. Each time a command is executed
* the engine will invoke this callback in order to consume the
* execution result (i.e. return value) of the last executed command.
*
* This callback is registered later via vedis_config() using VEDIS_CONFIG_OUTPUT_CONSUMER
* as a configuration option.
*/
static int command_result_render(vedis_value *pResult,void *pUnused /* userdata */)
{
const char *zResult = 0;
if( vedis_value_is_null(pResult) ){
zResult = "<null>";
}else if( vedis_value_is_array(pResult) ){
struct array_rend sRend = { 1 , 0 };
/* Command return an array, render it */
vedis_array_walk(pResult,array_render,&sRend);
}else{
/* Explicitly cast the result to a null terminated string */
zResult = vedis_value_to_string(pResult,0);
}
if( zResult ){
puts(zResult);
}
return VEDIS_OK;
}
/* Vedis shell */
int main(int argc,char **argv)
{
char zBuf[4096],*zPtr; /* Read buffer */
vedis *pStore; /* Vedis handle */
int rc;
/* Create our datastore */
rc = vedis_open(&pStore,argc > 1 ? argv[1] /* An on-disk data store */ : ":mem:" /* An in-memory data store*/);
if( rc != VEDIS_OK ){
/* Seriously? */
Fatal("Vedis is running out of memory");
}
/* Register the result (command return value) consumer callback */
vedis_config(pStore,VEDIS_CONFIG_OUTPUT_CONSUMER,command_result_render,0 /* userdata */);
/* Register the atexit() callback */
atexit(vedis_exit);
/* Start the shell */
puts(zBanner);
for(;;){
fputs("vedis>",stdout);
zPtr = fgets(zBuf,sizeof(zBuf),stdin);
if( !zPtr || isBlank(zBuf,sizeof(zBuf)) ){
/* Blank line - exit */
puts("Exiting...comitting the transaction");
break;
}
/* Exectute the command */
rc = vedis_exec(pStore,zBuf,-1);
if( rc != VEDIS_OK ){
/* Error during execution. Extract the error log */
const char *zErr;
int nLen;
vedis_config(pStore,VEDIS_CONFIG_ERR_LOG,&zErr,&nLen);
if( nLen > 0 ){
puts(zErr);
}
if( rc != VEDIS_UNKNOWN /* Unknown command */){
/* Exit immediately */
break;
}
}
}/* for(;;) */
/* Auto-commit and close the vedis handle */
vedis_close(pStore);
return 0;
}
/*
* Array walker callback: Output array fields.
*
* This function is passed to the array_walk() interface which is
* invoked for each array entry.
*/
static int array_render(vedis_value *pEntry,void *pUserdata)
{
struct array_rend *pRend = (struct array_rend *)pUserdata;
const char *zValue;
int nByte;
if( vedis_value_is_null(pEntry) ){
zValue = "<null>";
nByte = (int)sizeof("<null>") - 1;
}else{
/* Extract entry contents */
zValue = vedis_value_to_string(pEntry,&nByte);
}
printf("%d) %.*s\n",++pRend->cnt,nByte,zValue);
return VEDIS_OK;
}