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 <string.h> 00021 #include <sys/time.h> 00022 #include <signal.h> 00023 #include <errno.h> 00024 #include <unistd.h> 00025 #include <dirent.h> 00026 #include <asterisk/channel.h> 00027 #include <asterisk/file.h> 00028 #include <asterisk/app.h> 00029 #include <asterisk/dsp.h> 00030 #include <asterisk/logger.h> 00031 #include <asterisk/options.h> 00032 #include <asterisk/astdb.h> 00033 #include <asterisk/cli.h> 00034 #include <asterisk/utils.h> 00035 #include <asterisk/lock.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 prefix[0] = '\0'; 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 value[valuelen - 1] = '\0'; 00173 } else { 00174 ast_log(LOG_NOTICE, "Strange, empty value for /%s/%s\n", family, keys); 00175 } 00176 } 00177 return res; 00178 } 00179 00180 int ast_db_del(const char *family, const char *keys) 00181 { 00182 char fullkey[256]; 00183 DBT key; 00184 int res, fullkeylen; 00185 00186 ast_mutex_lock(&dblock); 00187 if (dbinit()) { 00188 ast_mutex_unlock(&dblock); 00189 return -1; 00190 } 00191 00192 fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys); 00193 memset(&key, 0, sizeof(key)); 00194 key.data = fullkey; 00195 key.size = fullkeylen + 1; 00196 00197 res = astdb->del(astdb, &key, 0); 00198 astdb->sync(astdb, 0); 00199 00200 ast_mutex_unlock(&dblock); 00201 00202 if (res) 00203 ast_log(LOG_DEBUG, "Unable to find key '%s' in family '%s'\n", keys, family); 00204 return res; 00205 } 00206 00207 static int database_put(int fd, int argc, char *argv[]) 00208 { 00209 int res; 00210 if (argc != 5) 00211 return RESULT_SHOWUSAGE; 00212 res = ast_db_put(argv[2], argv[3], argv[4]); 00213 if (res) 00214 ast_cli(fd, "Failed to update entry\n"); 00215 else 00216 ast_cli(fd, "Updated database successfully\n"); 00217 return RESULT_SUCCESS; 00218 } 00219 00220 static int database_get(int fd, int argc, char *argv[]) 00221 { 00222 int res; 00223 char tmp[256]; 00224 if (argc != 4) 00225 return RESULT_SHOWUSAGE; 00226 res = ast_db_get(argv[2], argv[3], tmp, sizeof(tmp)); 00227 if (res) 00228 ast_cli(fd, "Database entry not found.\n"); 00229 else 00230 ast_cli(fd, "Value: %s\n", tmp); 00231 return RESULT_SUCCESS; 00232 } 00233 00234 static int database_del(int fd, int argc, char *argv[]) 00235 { 00236 int res; 00237 if (argc != 4) 00238 return RESULT_SHOWUSAGE; 00239 res = ast_db_del(argv[2], argv[3]); 00240 if (res) 00241 ast_cli(fd, "Database entry does not exist.\n"); 00242 else 00243 ast_cli(fd, "Database entry removed.\n"); 00244 return RESULT_SUCCESS; 00245 } 00246 00247 static int database_deltree(int fd, int argc, char *argv[]) 00248 { 00249 int res; 00250 if ((argc < 3) || (argc > 4)) 00251 return RESULT_SHOWUSAGE; 00252 if (argc == 4) 00253 res = ast_db_deltree(argv[2], argv[3]); 00254 else 00255 res = ast_db_deltree(argv[2], NULL); 00256 if (res) 00257 ast_cli(fd, "Database entries do not exist.\n"); 00258 else 00259 ast_cli(fd, "Database entries removed.\n"); 00260 return RESULT_SUCCESS; 00261 } 00262 00263 static int database_show(int fd, int argc, char *argv[]) 00264 { 00265 char prefix[256]; 00266 DBT key, data; 00267 char *keys, *values; 00268 int res; 00269 int pass; 00270 00271 if (argc == 4) { 00272 /* Family and key tree */ 00273 snprintf(prefix, sizeof(prefix), "/%s/%s", argv[2], argv[3]); 00274 } else if (argc == 3) { 00275 /* Family only */ 00276 snprintf(prefix, sizeof(prefix), "/%s", argv[2]); 00277 } else if (argc == 2) { 00278 /* Neither */ 00279 prefix[0] = '\0'; 00280 } else 00281 return RESULT_SHOWUSAGE; 00282 ast_mutex_lock(&dblock); 00283 if (dbinit()) { 00284 ast_mutex_unlock(&dblock); 00285 ast_cli(fd, "Database unavailable\n"); 00286 return RESULT_SUCCESS; 00287 } 00288 memset(&key, 0, sizeof(key)); 00289 memset(&data, 0, sizeof(data)); 00290 pass = 0; 00291 while(!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) { 00292 if (key.size) { 00293 keys = key.data; 00294 keys[key.size - 1] = '\0'; 00295 } else 00296 keys = "<bad key>"; 00297 if (data.size) { 00298 values = data.data; 00299 values[data.size - 1]='\0'; 00300 } else 00301 values = "<bad value>"; 00302 if (keymatch(keys, prefix)) { 00303 ast_cli(fd, "%-50s: %-25s\n", keys, values); 00304 } 00305 } 00306 ast_mutex_unlock(&dblock); 00307 return RESULT_SUCCESS; 00308 } 00309 00310 struct ast_db_entry *ast_db_gettree(const char *family, const char *keytree) 00311 { 00312 char prefix[256]; 00313 DBT key, data; 00314 char *keys, *values; 00315 int res; 00316 int pass; 00317 struct ast_db_entry *last = NULL; 00318 struct ast_db_entry *cur, *ret=NULL; 00319 00320 if (family && !ast_strlen_zero(family)) { 00321 if (keytree && !ast_strlen_zero(keytree)) 00322 /* Family and key tree */ 00323 snprintf(prefix, sizeof(prefix), "/%s/%s", family, prefix); 00324 else 00325 /* Family only */ 00326 snprintf(prefix, sizeof(prefix), "/%s", family); 00327 } else 00328 prefix[0] = '\0'; 00329 ast_mutex_lock(&dblock); 00330 if (dbinit()) { 00331 ast_mutex_unlock(&dblock); 00332 ast_log(LOG_WARNING, "Database unavailable\n"); 00333 return NULL; 00334 } 00335 memset(&key, 0, sizeof(key)); 00336 memset(&data, 0, sizeof(data)); 00337 pass = 0; 00338 while(!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) { 00339 if (key.size) { 00340 keys = key.data; 00341 keys[key.size - 1] = '\0'; 00342 } else 00343 keys = "<bad key>"; 00344 if (data.size) { 00345 values = data.data; 00346 values[data.size - 1]='\0'; 00347 } else 00348 values = "<bad value>"; 00349 if (keymatch(keys, prefix)) { 00350 cur = malloc(sizeof(struct ast_db_entry) + strlen(keys) + strlen(values) + 2); 00351 if (cur) { 00352 cur->next = NULL; 00353 cur->key = cur->data + strlen(values) + 1; 00354 strcpy(cur->data, values); 00355 strcpy(cur->key, keys); 00356 if (last) 00357 last->next = cur; 00358 else 00359 ret = cur; 00360 last = cur; 00361 } 00362 } 00363 } 00364 ast_mutex_unlock(&dblock); 00365 return ret; 00366 } 00367 00368 void ast_db_freetree(struct ast_db_entry *dbe) 00369 { 00370 struct ast_db_entry *last; 00371 while(dbe) { 00372 last = dbe; 00373 dbe = dbe->next; 00374 free(last); 00375 } 00376 } 00377 00378 static char database_show_usage[] = 00379 "Usage: database show [family [keytree]]\n" 00380 " Shows Asterisk database contents, optionally restricted\n" 00381 "to a given family, or family and keytree.\n"; 00382 00383 static char database_put_usage[] = 00384 "Usage: database put <family> <key> <value>\n" 00385 " Adds or updates an entry in the Asterisk database for\n" 00386 "a given family, key, and value.\n"; 00387 00388 static char database_get_usage[] = 00389 "Usage: database get <family> <key>\n" 00390 " Retrieves an entry in the Asterisk database for a given\n" 00391 "family and key.\n"; 00392 00393 static char database_del_usage[] = 00394 "Usage: database del <family> <key>\n" 00395 " Deletes an entry in the Asterisk database for a given\n" 00396 "family and key.\n"; 00397 00398 static char database_deltree_usage[] = 00399 "Usage: database deltree <family> [keytree]\n" 00400 " Deletes a family or specific keytree within a family\n" 00401 "in the Asterisk database.\n"; 00402 00403 struct ast_cli_entry cli_database_show = 00404 { { "database", "show", NULL }, database_show, "Shows database contents", database_show_usage }; 00405 00406 struct ast_cli_entry cli_database_get = 00407 { { "database", "get", NULL }, database_get, "Gets database value", database_get_usage }; 00408 00409 struct ast_cli_entry cli_database_put = 00410 { { "database", "put", NULL }, database_put, "Adds/updates database value", database_put_usage }; 00411 00412 struct ast_cli_entry cli_database_del = 00413 { { "database", "del", NULL }, database_del, "Removes database key/value", database_del_usage }; 00414 00415 struct ast_cli_entry cli_database_deltree = 00416 { { "database", "deltree", NULL }, database_deltree, "Removes database keytree/values", database_deltree_usage }; 00417 00418 int astdb_init(void) 00419 { 00420 dbinit(); 00421 ast_cli_register(&cli_database_show); 00422 ast_cli_register(&cli_database_get); 00423 ast_cli_register(&cli_database_put); 00424 ast_cli_register(&cli_database_del); 00425 ast_cli_register(&cli_database_deltree); 00426 return 0; 00427 }

Generated on Fri Sep 24 21:03:46 2004 for Asterisk by doxygen 1.3.8