Scope Tracing: A new facility for tracing scope enter/exit
[asterisk/asterisk.git] / res / res_realtime.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Anthony Minessale <anthmct@yahoo.com>
7  * Mark Spencer <markster@digium.com>
8  *
9  * See http://www.asterisk.org for more information about
10  * the Asterisk project. Please do not directly contact
11  * any of the maintainers of this project for assistance;
12  * the project provides a web site, mailing lists and IRC
13  * channels for your use.
14  *
15  * This program is free software, distributed under the terms of
16  * the GNU General Public License Version 2. See the LICENSE file
17  * at the top of the source tree.
18  */
19
20 /*! \file
21  *
22  * \brief RealTime CLI
23  *
24  * \author Anthony Minessale <anthmct@yahoo.com>
25  * \author Mark Spencer <markster@digium.com>
26  *
27  * \ingroup applications
28  */
29
30 /*** MODULEINFO
31         <support_level>core</support_level>
32  ***/
33
34 #include "asterisk.h"
35
36 #include "asterisk/file.h"
37 #include "asterisk/channel.h"
38 #include "asterisk/pbx.h"
39 #include "asterisk/config.h"
40 #include "asterisk/module.h"
41 #include "asterisk/lock.h"
42 #include "asterisk/cli.h"
43
44
45 static char *cli_realtime_load(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
46 {
47 #define CRL_HEADER_FORMAT "%30s  %-30s\n"
48         struct ast_variable *var = NULL, *orig_var = NULL;
49
50         switch (cmd) {
51         case CLI_INIT:
52                 e->command = "realtime load";
53                 e->usage =
54                         "Usage: realtime load <family> <colmatch> <value>\n"
55                         "       Prints out a list of variables using the RealTime driver.\n"
56                         "       You must supply a family name, a column to match on, and a value to match to.\n";
57                 return NULL;
58         case CLI_GENERATE:
59                 return NULL;
60         }
61
62
63         if (a->argc < 5)
64                 return CLI_SHOWUSAGE;
65
66         var = ast_load_realtime_all(a->argv[2], a->argv[3], a->argv[4], SENTINEL);
67
68         if (var) {
69                 ast_cli(a->fd, CRL_HEADER_FORMAT, "Column Name", "Column Value");
70                 ast_cli(a->fd, CRL_HEADER_FORMAT, "--------------------", "--------------------");
71                 orig_var = var;
72                 while (var) {
73                         ast_cli(a->fd, CRL_HEADER_FORMAT, var->name, var->value);
74                         var = var->next;
75                 }
76         } else {
77                 ast_cli(a->fd, "No rows found matching search criteria.\n");
78         }
79         ast_variables_destroy(orig_var);
80         return CLI_SUCCESS;
81 }
82
83 static char *cli_realtime_update(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
84 {
85         int res = 0;
86
87         switch (cmd) {
88         case CLI_INIT:
89                 e->command = "realtime update";
90                 e->usage =
91                         "Usage: realtime update <family> <colmatch> <valuematch> <colupdate> <newvalue>\n"
92                         "       Update a single variable using the RealTime driver.\n"
93                         "       You must supply a family name, a column to update on, a new value, column to match, and value to match.\n"
94                         "       Ex: realtime update sippeers name bobsphone port 4343\n"
95                         "       will execute SQL as UPDATE sippeers SET port = 4343 WHERE name = bobsphone\n";
96                 return NULL;
97         case CLI_GENERATE:
98                 return NULL;
99         }
100
101         if (a->argc < 7)
102                 return CLI_SHOWUSAGE;
103
104         res = ast_update_realtime(a->argv[2], a->argv[3], a->argv[4], a->argv[5], a->argv[6], SENTINEL);
105
106         if (res < 0) {
107                 ast_cli(a->fd, "Failed to update. Check the debug log for possible SQL related entries.\n");
108                 return CLI_FAILURE;
109         }
110
111         ast_cli(a->fd, "Updated %d RealTime record%s.\n", res, ESS(res));
112
113         return CLI_SUCCESS;
114 }
115
116 static char *cli_realtime_update2(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
117 {
118         int res = -1;
119
120         switch (cmd) {
121         case CLI_INIT:
122                 e->command = "realtime update2";
123                 e->usage =
124                         "Usage: realtime update2 <family> <colmatch> <valuematch> [... <colmatch5> <valuematch5>] NULL <colupdate> <newvalue>\n"
125                         "       Update a single variable, requiring one or more fields to match using the\n"
126                         "       RealTime driver. You must supply a family name, a column to update, a new\n"
127                         "       value, and at least one column and value to match.\n"
128                         "       Ex: realtime update2 sippeers name bobsphone ipaddr 127.0.0.1 NULL port 4343\n"
129                         "       will execute SQL as\n"
130                         "       UPDATE sippeers SET port='4343' WHERE name='bobsphone' and ipaddr='127.0.0.1'\n";
131                 return NULL;
132         case CLI_GENERATE:
133                 return NULL;
134         }
135
136         /* Make sure we have the right number of arguments and that the required literal NULL
137            is present */
138         if (a->argc < 8 || a->argc > 16 || a->argc % 2
139            || strcmp(a->argv[a->argc - 3], "NULL")) {
140                 return CLI_SHOWUSAGE;
141         }
142
143         if (a->argc == 8) {
144                 res = ast_update2_realtime(
145                         a->argv[2], a->argv[3], a->argv[4], SENTINEL,
146                         a->argv[6], a->argv[7], SENTINEL);
147         } else if (a->argc == 10) {
148                 res = ast_update2_realtime(
149                         a->argv[2], a->argv[3], a->argv[4], a->argv[5],
150                         a->argv[6], SENTINEL,
151                         a->argv[8], a->argv[9], SENTINEL);
152         } else if (a->argc == 12) {
153                 res = ast_update2_realtime(
154                         a->argv[2], a->argv[3], a->argv[4], a->argv[5],
155                         a->argv[6], a->argv[7], a->argv[8], SENTINEL,
156                         a->argv[10], a->argv[11], SENTINEL);
157         } else if (a->argc == 14) {
158                 res = ast_update2_realtime(
159                         a->argv[2], a->argv[3], a->argv[4], a->argv[5],
160                         a->argv[6], a->argv[7], a->argv[8], a->argv[9],
161                         a->argv[10], SENTINEL,
162                         a->argv[12], a->argv[13], SENTINEL);
163         } else if (a->argc == 16) {
164                 res = ast_update2_realtime(
165                         a->argv[2], a->argv[3], a->argv[4], a->argv[5],
166                         a->argv[6], a->argv[7], a->argv[8], a->argv[9],
167                         a->argv[10], a->argv[11], a->argv[12], SENTINEL,
168                         a->argv[14], a->argv[15], SENTINEL);
169         }
170
171         if (res < 0) {
172                 ast_cli(a->fd, "Failed to update. Check the debug log for possible SQL related entries.\n");
173                 return CLI_FAILURE;
174         }
175
176         ast_cli(a->fd, "Updated %d RealTime record%s.\n", res, ESS(res));
177
178         return CLI_SUCCESS;
179 }
180
181 static char *cli_realtime_store(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
182 {
183         int res = -1;
184
185         switch (cmd) {
186         case CLI_INIT:
187                 e->command = "realtime store";
188                 e->usage =
189                         "Usage: realtime store <family> <colname1> <value1> [<colname2> <value2> [... <colname5> <value5>]]\n"
190                         "       Create a stored row using the RealTime driver.\n"
191                         "       You must supply a family name and name/value pairs (up to 5).  If\n"
192                         "       you need to store more than 5 key/value pairs, start with the first\n"
193                         "       five, then use 'realtime update' or 'realtime update2' to add\n"
194                         "       additional columns.\n";
195                 return NULL;
196         case CLI_GENERATE:
197                 return NULL;
198         }
199
200         if (a->argc < 5) {
201                 return CLI_SHOWUSAGE;
202         } else if (a->argc == 5) {
203                 res = ast_store_realtime(a->argv[2], a->argv[3], a->argv[4], SENTINEL);
204         } else if (a->argc == 7) {
205                 res = ast_store_realtime(a->argv[2], a->argv[3], a->argv[4], a->argv[5], a->argv[6], SENTINEL);
206         } else if (a->argc == 9) {
207                 res = ast_store_realtime(a->argv[2], a->argv[3], a->argv[4], a->argv[5], a->argv[6], a->argv[7], a->argv[8], SENTINEL);
208         } else if (a->argc == 11) {
209                 res = ast_store_realtime(a->argv[2], a->argv[3], a->argv[4], a->argv[5], a->argv[6], a->argv[7], a->argv[8], a->argv[9], a->argv[10], SENTINEL);
210         } else if (a->argc == 13) {
211                 res = ast_store_realtime(a->argv[2], a->argv[3], a->argv[4], a->argv[5], a->argv[6], a->argv[7], a->argv[8], a->argv[9], a->argv[10], a->argv[11], a->argv[12], SENTINEL);
212         } else {
213                 return CLI_SHOWUSAGE;
214         }
215
216         if (res < 0) {
217                 ast_cli(a->fd, "Failed to store record. Check the debug log for possible SQL related entries.\n");
218                 return CLI_FAILURE;
219         }
220
221         ast_cli(a->fd, "Stored RealTime record.\n");
222
223         return CLI_SUCCESS;
224 }
225
226 static char *cli_realtime_destroy(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
227 {
228         int res = -1;
229
230         switch (cmd) {
231         case CLI_INIT:
232                 e->command = "realtime destroy";
233                 e->usage =
234                         "Usage: realtime destroy <family> <colmatch1> <valuematch1> [<colmatch2> <valuematch2> [... <colmatch5> <valuematch5>]]\n"
235                         "       Remove a stored row using the RealTime driver.\n"
236                         "       You must supply a family name and name/value pairs (up to 5).\n";
237                 return NULL;
238         case CLI_GENERATE:
239                 return NULL;
240         }
241
242         if (a->argc < 5) {
243                 return CLI_SHOWUSAGE;
244         } else if (a->argc == 5) {
245                 res = ast_destroy_realtime(a->argv[2], a->argv[3], a->argv[4], SENTINEL);
246         } else if (a->argc == 7) {
247                 res = ast_destroy_realtime(a->argv[2], a->argv[3], a->argv[4], a->argv[5], a->argv[6], SENTINEL);
248         } else if (a->argc == 9) {
249                 res = ast_destroy_realtime(a->argv[2], a->argv[3], a->argv[4], a->argv[5], a->argv[6], a->argv[7], a->argv[8], SENTINEL);
250         } else if (a->argc == 11) {
251                 res = ast_destroy_realtime(a->argv[2], a->argv[3], a->argv[4], a->argv[5], a->argv[6], a->argv[7], a->argv[8], a->argv[9], a->argv[10], SENTINEL);
252         } else if (a->argc == 13) {
253                 res = ast_destroy_realtime(a->argv[2], a->argv[3], a->argv[4], a->argv[5], a->argv[6], a->argv[7], a->argv[8], a->argv[9], a->argv[10], a->argv[11], a->argv[12], SENTINEL);
254         } else {
255                 return CLI_SHOWUSAGE;
256         }
257
258         if (res < 0) {
259                 ast_cli(a->fd, "Failed to remove record. Check the debug log for possible SQL related entries.\n");
260                 return CLI_FAILURE;
261         }
262
263         ast_cli(a->fd, "Removed %d RealTime record%s.\n", res, ESS(res));
264
265         return CLI_SUCCESS;
266 }
267
268 static struct ast_cli_entry cli_realtime[] = {
269         AST_CLI_DEFINE(cli_realtime_load, "Used to print out RealTime variables."),
270         AST_CLI_DEFINE(cli_realtime_update, "Used to update RealTime variables."),
271         AST_CLI_DEFINE(cli_realtime_update2, "Used to test the RealTime update2 method"),
272         AST_CLI_DEFINE(cli_realtime_store, "Store a new row into a RealTime database"),
273         AST_CLI_DEFINE(cli_realtime_destroy, "Delete a row from a RealTime database"),
274 };
275
276 static int unload_module(void)
277 {
278         ast_cli_unregister_multiple(cli_realtime, ARRAY_LEN(cli_realtime));
279         return 0;
280 }
281
282 static int load_module(void)
283 {
284         ast_cli_register_multiple(cli_realtime, ARRAY_LEN(cli_realtime));
285         return AST_MODULE_LOAD_SUCCESS;
286 }
287
288 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Realtime Data Lookup/Rewrite");