Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals

db.c

Go to the documentation of this file.
00001 /* 00002 * Asterisk -- A telephony toolkit for Linux. 00003 * 00004 * Channel Management 00005 * 00006 * Copyright (C) 1999, Mark Spencer 00007 * 00008 * Mark Spencer <markster@linux-support.net> 00009 * 00010 * This program is free software, distributed under the terms of 00011 * the GNU General Public License 00012 */ 00013 00014 /* DB3 is licensed under Sleepycat Public License and is thus incompatible 00015 with GPL. To avoid having to make another exception (and complicate 00016 licensing even further) we elect to use DB1 which is BSD licensed */ 00017 00018 #include <stdio.h> 00019 #include <stdlib.h> 00020 #include <pthread.h> 00021 #include <string.h> 00022 #include <sys/time.h> 00023 #include <signal.h> 00024 #include <errno.h> 00025 #include <unistd.h> 00026 #include <dirent.h> 00027 #include <asterisk/channel.h> 00028 #include <asterisk/file.h> 00029 #include <asterisk/app.h> 00030 #include <asterisk/dsp.h> 00031 #include <asterisk/logger.h> 00032 #include <asterisk/options.h> 00033 #include <asterisk/astdb.h> 00034 #include <asterisk/cli.h> 00035 #include <asterisk/utils.h> 00036 #include "db1-ast/include/db.h" 00037 #include "asterisk.h" 00038 #include "astconf.h" 00039 00040 static DB *astdb; 00041 AST_MUTEX_DEFINE_STATIC(dblock); 00042 00043 static int dbinit(void) 00044 { 00045 if (!astdb) { 00046 if (!(astdb = dbopen((char *)ast_config_AST_DB, O_CREAT | O_RDWR, 0664, DB_BTREE, NULL))) { 00047 ast_log(LOG_WARNING, "Unable to open Asterisk database\n"); 00048 } 00049 } 00050 if (astdb) 00051 return 0; 00052 return -1; 00053 } 00054 00055 00056 static inline int keymatch(const char *key, const char *prefix) 00057 { 00058 int preflen = strlen(prefix); 00059 if (!preflen) 00060 return 1; 00061 if (!strcasecmp(key, prefix)) 00062 return 1; 00063 if ((strlen(key) > preflen) && 00064 !strncasecmp(key, prefix, preflen)) { 00065 if (key[preflen] == '/') 00066 return 1; 00067 } 00068 return 0; 00069 } 00070 00071 int ast_db_deltree(const char *family, const char *keytree) 00072 { 00073 char prefix[256]; 00074 DBT key, data; 00075 char *keys; 00076 int res; 00077 int pass; 00078 00079 if (family) { 00080 if (keytree) 00081 snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree); 00082 else 00083 snprintf(prefix, sizeof(prefix), "/%s", family); 00084 } else if (keytree) 00085 return -1; 00086 else 00087 strcpy(prefix, ""); 00088 00089 ast_mutex_lock(&dblock); 00090 if (dbinit()) 00091 return -1; 00092 00093 memset(&key, 0, sizeof(key)); 00094 memset(&data, 0, sizeof(data)); 00095 pass = 0; 00096 while(!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) { 00097 if (key.size) { 00098 keys = key.data; 00099 keys[key.size - 1] = '\0'; 00100 } else 00101 keys = "<bad key>"; 00102 if (keymatch(keys, prefix)) { 00103 astdb->del(astdb, &key, 0); 00104 } 00105 } 00106 astdb->sync(astdb, 0); 00107 ast_mutex_unlock(&dblock); 00108 return 0; 00109 } 00110 00111 int ast_db_put(const char *family, const char *keys, char *value) 00112 { 00113 char fullkey[256]; 00114 DBT key, data; 00115 int res, fullkeylen; 00116 00117 ast_mutex_lock(&dblock); 00118 if (dbinit()) { 00119 ast_mutex_unlock(&dblock); 00120 return -1; 00121 } 00122 00123 fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys); 00124 memset(&key, 0, sizeof(key)); 00125 memset(&data, 0, sizeof(data)); 00126 key.data = fullkey; 00127 key.size = fullkeylen + 1; 00128 data.data = value; 00129 data.size = strlen(value) + 1; 00130 res = astdb->put(astdb, &key, &data, 0); 00131 astdb->sync(astdb, 0); 00132 ast_mutex_unlock(&dblock); 00133 if (res) 00134 ast_log(LOG_WARNING, "Unable to put value '%s' for key '%s' in family '%s'\n", value, keys, family); 00135 return res; 00136 } 00137 00138 int ast_db_get(const char *family, const char *keys, char *value, int valuelen) 00139 { 00140 char fullkey[256]=""; 00141 DBT key, data; 00142 int res, fullkeylen; 00143 00144 ast_mutex_lock(&dblock); 00145 if (dbinit()) { 00146 ast_mutex_unlock(&dblock); 00147 return -1; 00148 } 00149 00150 fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys); 00151 memset(&key, 0, sizeof(key)); 00152 memset(&data, 0, sizeof(data)); 00153 memset(value, 0, valuelen); 00154 key.data = fullkey; 00155 key.size = fullkeylen + 1; 00156 00157 res = astdb->get(astdb, &key, &data, 0); 00158 00159 ast_mutex_unlock(&dblock); 00160 00161 /* Be sure to NULL terminate our data either way */ 00162 if (res) { 00163 ast_log(LOG_DEBUG, "Unable to find key '%s' in family '%s'\n", keys, family); 00164 } else { 00165 #if 0 00166 printf("Got value of size %d\n", data.size); 00167 #endif 00168 if (data.size) { 00169 ((char *)data.data)[data.size - 1] = '\0'; 00170 /* Make sure that we don't write too much to the dst pointer or we don't read too much from the source pointer */ 00171 strncpy(value, data.data, (valuelen > data.size) ? data.size : valuelen); 00172 } else { 00173 ast_log(LOG_NOTICE, "Strange, empty value for /%s/%s\n", family, keys); 00174 } 00175 } 00176 return res; 00177 } 00178 00179 int ast_db_del(const char *family, const char *keys) 00180 { 00181 char fullkey[256]; 00182 DBT key; 00183 int res, fullkeylen; 00184 00185 ast_mutex_lock(&dblock); 00186 if (dbinit()) { 00187 ast_mutex_unlock(&dblock); 00188 return -1; 00189 } 00190 00191 fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys); 00192 memset(&key, 0, sizeof(key)); 00193 key.data = fullkey; 00194 key.size = fullkeylen + 1; 00195 00196 res = astdb->del(astdb, &key, 0); 00197 astdb->sync(astdb, 0); 00198 00199 ast_mutex_unlock(&dblock); 00200 00201 if (res) 00202 ast_log(LOG_DEBUG, "Unable to find key '%s' in family '%s'\n", keys, family); 00203 return res; 00204 } 00205 00206 static int database_put(int fd, int argc, char *argv[]) 00207 { 00208 int res; 00209 if (argc != 5) 00210 return RESULT_SHOWUSAGE; 00211 res = ast_db_put(argv[2], argv[3], argv[4]); 00212 if (res) 00213 ast_cli(fd, "Failed to update entry\n"); 00214 else 00215 ast_cli(fd, "Updated database successfully\n"); 00216 return RESULT_SUCCESS; 00217 } 00218 00219 static int database_get(int fd, int argc, char *argv[]) 00220 { 00221 int res; 00222 char tmp[256]; 00223 if (argc != 4) 00224 return RESULT_SHOWUSAGE; 00225 res = ast_db_get(argv[2], argv[3], tmp, sizeof(tmp)); 00226 if (res) 00227 ast_cli(fd, "Database entry not found.\n"); 00228 else 00229 ast_cli(fd, "Value: %s\n", tmp); 00230 return RESULT_SUCCESS; 00231 } 00232 00233 static int database_del(int fd, int argc, char *argv[]) 00234 { 00235 int res; 00236 if (argc != 4) 00237 return RESULT_SHOWUSAGE; 00238 res = ast_db_del(argv[2], argv[3]); 00239 if (res) 00240 ast_cli(fd, "Database entry does not exist.\n"); 00241 else 00242 ast_cli(fd, "Database entry removed.\n"); 00243 return RESULT_SUCCESS; 00244 } 00245 00246 static int database_deltree(int fd, int argc, char *argv[]) 00247 { 00248 int res; 00249 if ((argc < 3) || (argc > 4)) 00250 return RESULT_SHOWUSAGE; 00251 if (argc == 4) 00252 res = ast_db_deltree(argv[2], argv[3]); 00253 else 00254 res = ast_db_deltree(argv[2], NULL); 00255 if (res) 00256 ast_cli(fd, "Database entries do not exist.\n"); 00257 else 00258 ast_cli(fd, "Database entries removed.\n"); 00259 return RESULT_SUCCESS; 00260 } 00261 00262 static int database_show(int fd, int argc, char *argv[]) 00263 { 00264 char prefix[256]; 00265 DBT key, data; 00266 char *keys, *values; 00267 int res; 00268 int pass; 00269 00270 if (argc == 4) { 00271 /* Family and key tree */ 00272 snprintf(prefix, sizeof(prefix), "/%s/%s", argv[2], argv[3]); 00273 } else if (argc == 3) { 00274 /* Family only */ 00275 snprintf(prefix, sizeof(prefix), "/%s", argv[2]); 00276 } else if (argc == 2) { 00277 /* Neither */ 00278 strcpy(prefix, ""); 00279 } else 00280 return RESULT_SHOWUSAGE; 00281 ast_mutex_lock(&dblock); 00282 if (dbinit()) { 00283 ast_mutex_unlock(&dblock); 00284 ast_cli(fd, "Database unavailable\n"); 00285 return RESULT_SUCCESS; 00286 } 00287 memset(&key, 0, sizeof(key)); 00288 memset(&data, 0, sizeof(data)); 00289 pass = 0; 00290 while(!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) { 00291 if (key.size) { 00292 keys = key.data; 00293 keys[key.size - 1] = '\0'; 00294 } else 00295 keys = "<bad key>"; 00296 if (data.size) { 00297 values = data.data; 00298 values[data.size - 1]='\0'; 00299 } else 00300 values = "<bad value>"; 00301 if (keymatch(keys, prefix)) { 00302 ast_cli(fd, "%-50s: %-25s\n", keys, values); 00303 } 00304 } 00305 ast_mutex_unlock(&dblock); 00306 return RESULT_SUCCESS; 00307 } 00308 00309 struct ast_db_entry *ast_db_gettree(const char *family, const char *keytree) 00310 { 00311 char prefix[256]; 00312 DBT key, data; 00313 char *keys, *values; 00314 int res; 00315 int pass; 00316 struct ast_db_entry *last = NULL; 00317 struct ast_db_entry *cur, *ret=NULL; 00318 00319 if (family && !ast_strlen_zero(family)) { 00320 if (keytree && !ast_strlen_zero(keytree)) 00321 /* Family and key tree */ 00322 snprintf(prefix, sizeof(prefix), "/%s/%s", family, prefix); 00323 else 00324 /* Family only */ 00325 snprintf(prefix, sizeof(prefix), "/%s", family); 00326 } else 00327 strcpy(prefix, ""); 00328 ast_mutex_lock(&dblock); 00329 if (dbinit()) { 00330 ast_mutex_unlock(&dblock); 00331 ast_log(LOG_WARNING, "Database unavailable\n"); 00332 return NULL; 00333 } 00334 memset(&key, 0, sizeof(key)); 00335 memset(&data, 0, sizeof(data)); 00336 pass = 0; 00337 while(!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) { 00338 if (key.size) { 00339 keys = key.data; 00340 keys[key.size - 1] = '\0'; 00341 } else 00342 keys = "<bad key>"; 00343 if (data.size) { 00344 values = data.data; 00345 values[data.size - 1]='\0'; 00346 } else 00347 values = "<bad value>"; 00348 if (keymatch(keys, prefix)) { 00349 cur = malloc(sizeof(struct ast_db_entry) + strlen(keys) + strlen(values) + 2); 00350 if (cur) { 00351 cur->next = NULL; 00352 cur->key = cur->data + strlen(values) + 1; 00353 strcpy(cur->data, values); 00354 strcpy(cur->key, keys); 00355 if (last) 00356 last->next = cur; 00357 else 00358 ret = cur; 00359 last = cur; 00360 } 00361 } 00362 } 00363 ast_mutex_unlock(&dblock); 00364 return ret; 00365 } 00366 00367 void ast_db_freetree(struct ast_db_entry *dbe) 00368 { 00369 struct ast_db_entry *last; 00370 while(dbe) { 00371 last = dbe; 00372 dbe = dbe->next; 00373 free(last); 00374 } 00375 } 00376 00377 static char database_show_usage[] = 00378 "Usage: database show [family [keytree]]\n" 00379 " Shows Asterisk database contents, optionally restricted\n" 00380 "to a given family, or family and keytree.\n"; 00381 00382 static char database_put_usage[] = 00383 "Usage: database put <family> <key> <value>\n" 00384 " Adds or updates an entry in the Asterisk database for\n" 00385 "a given family, key, and value.\n"; 00386 00387 static char database_get_usage[] = 00388 "Usage: database get <family> <key>\n" 00389 " Retrieves an entry in the Asterisk database for a given\n" 00390 "family and key.\n"; 00391 00392 static char database_del_usage[] = 00393 "Usage: database del <family> <key>\n" 00394 " Deletes an entry in the Asterisk database for a given\n" 00395 "family and key.\n"; 00396 00397 static char database_deltree_usage[] = 00398 "Usage: database deltree <family> [keytree]\n" 00399 " Deletes a family or specific keytree within a family\n" 00400 "in the Asterisk database.\n"; 00401 00402 struct ast_cli_entry cli_database_show = 00403 { { "database", "show", NULL }, database_show, "Shows database contents", database_show_usage }; 00404 00405 struct ast_cli_entry cli_database_get = 00406 { { "database", "get", NULL }, database_get, "Gets database value", database_get_usage }; 00407 00408 struct ast_cli_entry cli_database_put = 00409 { { "database", "put", NULL }, database_put, "Adds/updates database value", database_put_usage }; 00410 00411 struct ast_cli_entry cli_database_del = 00412 { { "database", "del", NULL }, database_del, "Removes database key/value", database_del_usage }; 00413 00414 struct ast_cli_entry cli_database_deltree = 00415 { { "database", "deltree", NULL }, database_deltree, "Removes database keytree/values", database_deltree_usage }; 00416 00417 int astdb_init(void) 00418 { 00419 dbinit(); 00420 ast_cli_register(&cli_database_show); 00421 ast_cli_register(&cli_database_get); 00422 ast_cli_register(&cli_database_put); 00423 ast_cli_register(&cli_database_del); 00424 ast_cli_register(&cli_database_deltree); 00425 return 0; 00426 }

Generated on Sat Jun 12 16:40:57 2004 for Asterisk by doxygen 1.3.7