Mon May 14 04:48:17 2007

Asterisk developer's documentation


db.c File Reference

ASTdb Management. More...

#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <dirent.h>
#include "asterisk/channel.h"
#include "asterisk/file.h"
#include "asterisk/app.h"
#include "asterisk/dsp.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/astdb.h"
#include "asterisk/cli.h"
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/manager.h"
#include <db1/db.h>

Include dependency graph for db.c:

Go to the source code of this file.

Functions

int ast_db_del (const char *family, const char *keys)
int ast_db_deltree (const char *family, const char *keytree)
void ast_db_freetree (struct ast_db_entry *dbe)
int ast_db_get (const char *family, const char *keys, char *value, int valuelen)
ast_db_entryast_db_gettree (const char *family, const char *keytree)
int ast_db_put (const char *family, const char *keys, char *value)
 AST_MUTEX_DEFINE_STATIC (dblock)
int astdb_init (void)
static int database_del (int fd, int argc, char *argv[])
static int database_deltree (int fd, int argc, char *argv[])
static int database_get (int fd, int argc, char *argv[])
static int database_put (int fd, int argc, char *argv[])
static int database_show (int fd, int argc, char *argv[])
static int database_showkey (int fd, int argc, char *argv[])
static int dbinit (void)
static int keymatch (const char *key, const char *prefix)
static int manager_dbget (struct mansession *s, const struct message *m)
static int manager_dbput (struct mansession *s, const struct message *m)
static int subkeymatch (const char *key, const char *suffix)

Variables

static DB * astdb
ast_cli_entry cli_database []
static char database_del_usage []
static char database_deltree_usage []
static char database_get_usage []
static char database_put_usage []
static char database_show_usage []
static char database_showkey_usage []


Detailed Description

ASTdb Management.

Author:
Mark Spencer <markster@digium.com>
Note:
DB3 is licensed under Sleepycat Public License and is thus incompatible with GPL. To avoid having to make another exception (and complicate licensing even further) we elect to use DB1 which is BSD licensed

Definition in file db.c.


Function Documentation

int ast_db_del ( const char *  family,
const char *  keys 
)

Definition at line 213 of file db.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dbinit(), key(), and LOG_DEBUG.

Referenced by __expire_registry(), ast_privacy_set(), auth_exec(), cache_lookup_internal(), database_del(), del_exec(), destroy_association(), dump_agents(), dump_queue_members(), function_db_delete(), handle_dbdel(), reload_agents(), reload_queue_members(), and update_registry().

00214 {
00215    char fullkey[256];
00216    DBT key;
00217    int res, fullkeylen;
00218 
00219    ast_mutex_lock(&dblock);
00220    if (dbinit()) {
00221       ast_mutex_unlock(&dblock);
00222       return -1;
00223    }
00224    
00225    fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
00226    memset(&key, 0, sizeof(key));
00227    key.data = fullkey;
00228    key.size = fullkeylen + 1;
00229    
00230    res = astdb->del(astdb, &key, 0);
00231    astdb->sync(astdb, 0);
00232    
00233    ast_mutex_unlock(&dblock);
00234 
00235    if (res) 
00236       ast_log(LOG_DEBUG, "Unable to find key '%s' in family '%s'\n", keys, family);
00237    return res;
00238 }

int ast_db_deltree ( const char *  family,
const char *  keytree 
)

Definition at line 100 of file db.c.

References ast_mutex_lock(), ast_mutex_unlock(), dbinit(), key(), keymatch(), keys, and prefix.

Referenced by ast_privacy_reset(), database_deltree(), deltree_exec(), dundi_flush(), handle_dbdeltree(), and iax_provision_reload().

00101 {
00102    char prefix[256];
00103    DBT key, data;
00104    char *keys;
00105    int res;
00106    int pass;
00107    
00108    if (family) {
00109       if (keytree) {
00110          snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree);
00111       } else {
00112          snprintf(prefix, sizeof(prefix), "/%s", family);
00113       }
00114    } else if (keytree) {
00115       return -1;
00116    } else {
00117       prefix[0] = '\0';
00118    }
00119    
00120    ast_mutex_lock(&dblock);
00121    if (dbinit()) {
00122       ast_mutex_unlock(&dblock);
00123       return -1;
00124    }
00125    
00126    memset(&key, 0, sizeof(key));
00127    memset(&data, 0, sizeof(data));
00128    pass = 0;
00129    while (!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
00130       if (key.size) {
00131          keys = key.data;
00132          keys[key.size - 1] = '\0';
00133       } else {
00134          keys = "<bad key>";
00135       }
00136       if (keymatch(keys, prefix)) {
00137          astdb->del(astdb, &key, 0);
00138       }
00139    }
00140    astdb->sync(astdb, 0);
00141    ast_mutex_unlock(&dblock);
00142    return 0;
00143 }

void ast_db_freetree ( struct ast_db_entry dbe  ) 

Definition at line 457 of file db.c.

References free, last, and ast_db_entry::next.

Referenced by reload_agents(), and reload_queue_members().

00458 {
00459    struct ast_db_entry *last;
00460    while (dbe) {
00461       last = dbe;
00462       dbe = dbe->next;
00463       free(last);
00464    }
00465 }

int ast_db_get ( const char *  family,
const char *  keys,
char *  value,
int  valuelen 
)

Definition at line 172 of file db.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dbinit(), key(), LOG_DEBUG, and LOG_NOTICE.

Referenced by ast_privacy_check(), auth_exec(), blacklist_read(), cache_lookup_internal(), check_access(), create_addr(), database_get(), database_increment(), function_db_delete(), function_db_exists(), function_db_read(), handle_dbget(), iax_provision_version(), load_password(), lookupblacklist_exec(), lookupcidname_exec(), manager_dbget(), populate_addr(), reg_source_db(), reload_agents(), and reload_queue_members().

00173 {
00174    char fullkey[256] = "";
00175    DBT key, data;
00176    int res, fullkeylen;
00177 
00178    ast_mutex_lock(&dblock);
00179    if (dbinit()) {
00180       ast_mutex_unlock(&dblock);
00181       return -1;
00182    }
00183 
00184    fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
00185    memset(&key, 0, sizeof(key));
00186    memset(&data, 0, sizeof(data));
00187    memset(value, 0, valuelen);
00188    key.data = fullkey;
00189    key.size = fullkeylen + 1;
00190    
00191    res = astdb->get(astdb, &key, &data, 0);
00192    
00193    ast_mutex_unlock(&dblock);
00194 
00195    /* Be sure to NULL terminate our data either way */
00196    if (res) {
00197       ast_log(LOG_DEBUG, "Unable to find key '%s' in family '%s'\n", keys, family);
00198    } else {
00199 #if 0
00200       printf("Got value of size %d\n", data.size);
00201 #endif
00202       if (data.size) {
00203          ((char *)data.data)[data.size - 1] = '\0';
00204          /* Make sure that we don't write too much to the dst pointer or we don't read too much from the source pointer */
00205          ast_copy_string(value, data.data, (valuelen > data.size) ? data.size : valuelen);
00206       } else {
00207          ast_log(LOG_NOTICE, "Strange, empty value for /%s/%s\n", family, keys);
00208       }
00209    }
00210    return res;
00211 }

struct ast_db_entry* ast_db_gettree ( const char *  family,
const char *  keytree 
)

Definition at line 395 of file db.c.

References ast_log(), ast_malloc, ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), ast_db_entry::data, dbinit(), key(), keymatch(), keys, last, LOG_WARNING, and prefix.

Referenced by reload_agents(), and reload_queue_members().

00396 {
00397    char prefix[256];
00398    DBT key, data;
00399    char *keys, *values;
00400    int values_len;
00401    int res;
00402    int pass;
00403    struct ast_db_entry *last = NULL;
00404    struct ast_db_entry *cur, *ret=NULL;
00405 
00406    if (!ast_strlen_zero(family)) {
00407       if (!ast_strlen_zero(keytree)) {
00408          /* Family and key tree */
00409          snprintf(prefix, sizeof(prefix), "/%s/%s", family, prefix);
00410       } else {
00411          /* Family only */
00412          snprintf(prefix, sizeof(prefix), "/%s", family);
00413       }
00414    } else {
00415       prefix[0] = '\0';
00416    }
00417    ast_mutex_lock(&dblock);
00418    if (dbinit()) {
00419       ast_mutex_unlock(&dblock);
00420       ast_log(LOG_WARNING, "Database unavailable\n");
00421       return NULL;   
00422    }
00423    memset(&key, 0, sizeof(key));
00424    memset(&data, 0, sizeof(data));
00425    pass = 0;
00426    while (!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
00427       if (key.size) {
00428          keys = key.data;
00429          keys[key.size - 1] = '\0';
00430       } else {
00431          keys = "<bad key>";
00432       }
00433       if (data.size) {
00434          values = data.data;
00435          values[data.size - 1] = '\0';
00436       } else {
00437          values = "<bad value>";
00438       }
00439       values_len = strlen(values) + 1;
00440       if (keymatch(keys, prefix) && (cur = ast_malloc(sizeof(*cur) + strlen(keys) + 1 + values_len))) {
00441          cur->next = NULL;
00442          cur->key = cur->data + values_len;
00443          strcpy(cur->data, values);
00444          strcpy(cur->key, keys);
00445          if (last) {
00446             last->next = cur;
00447          } else {
00448             ret = cur;
00449          }
00450          last = cur;
00451       }
00452    }
00453    ast_mutex_unlock(&dblock);
00454    return ret; 
00455 }

int ast_db_put ( const char *  family,
const char *  keys,
char *  value 
)

Definition at line 145 of file db.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), dbinit(), key(), and LOG_WARNING.

Referenced by ast_privacy_set(), cache_save(), cache_save_hint(), database_increment(), database_put(), dump_agents(), dump_queue_members(), function_db_write(), handle_command_response(), handle_dbput(), iax_provision_build(), manager_dbput(), mgcp_ss(), parse_register_contact(), save_secret(), ss_thread(), and update_registry().

00146 {
00147    char fullkey[256];
00148    DBT key, data;
00149    int res, fullkeylen;
00150 
00151    ast_mutex_lock(&dblock);
00152    if (dbinit()) {
00153       ast_mutex_unlock(&dblock);
00154       return -1;
00155    }
00156 
00157    fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
00158    memset(&key, 0, sizeof(key));
00159    memset(&data, 0, sizeof(data));
00160    key.data = fullkey;
00161    key.size = fullkeylen + 1;
00162    data.data = value;
00163    data.size = strlen(value) + 1;
00164    res = astdb->put(astdb, &key, &data, 0);
00165    astdb->sync(astdb, 0);
00166    ast_mutex_unlock(&dblock);
00167    if (res)
00168       ast_log(LOG_WARNING, "Unable to put value '%s' for key '%s' in family '%s'\n", value, keys, family);
00169    return res;
00170 }

AST_MUTEX_DEFINE_STATIC ( dblock   ) 

int astdb_init ( void   ) 

Provided by db.c

Definition at line 588 of file db.c.

References ast_cli_register_multiple(), ast_manager_register, cli_database, dbinit(), EVENT_FLAG_SYSTEM, manager_dbget(), and manager_dbput().

Referenced by main().

00589 {
00590    dbinit();
00591    ast_cli_register_multiple(cli_database, sizeof(cli_database) / sizeof(struct ast_cli_entry));
00592    ast_manager_register("DBGet", EVENT_FLAG_SYSTEM, manager_dbget, "Get DB Entry");
00593    ast_manager_register("DBPut", EVENT_FLAG_SYSTEM, manager_dbput, "Put DB Entry");
00594    return 0;
00595 }

static int database_del ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 269 of file db.c.

References ast_cli(), ast_db_del(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00270 {
00271    int res;
00272    if (argc != 4)
00273       return RESULT_SHOWUSAGE;
00274    res = ast_db_del(argv[2], argv[3]);
00275    if (res) {
00276       ast_cli(fd, "Database entry does not exist.\n");
00277    } else {
00278       ast_cli(fd, "Database entry removed.\n");
00279    }
00280    return RESULT_SUCCESS;
00281 }

static int database_deltree ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 283 of file db.c.

References ast_cli(), ast_db_deltree(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00284 {
00285    int res;
00286    if ((argc < 3) || (argc > 4))
00287       return RESULT_SHOWUSAGE;
00288    if (argc == 4) {
00289       res = ast_db_deltree(argv[2], argv[3]);
00290    } else {
00291       res = ast_db_deltree(argv[2], NULL);
00292    }
00293    if (res) {
00294       ast_cli(fd, "Database entries do not exist.\n");
00295    } else {
00296       ast_cli(fd, "Database entries removed.\n");
00297    }
00298    return RESULT_SUCCESS;
00299 }

static int database_get ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 254 of file db.c.

References ast_cli(), ast_db_get(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00255 {
00256    int res;
00257    char tmp[256];
00258    if (argc != 4)
00259       return RESULT_SHOWUSAGE;
00260    res = ast_db_get(argv[2], argv[3], tmp, sizeof(tmp));
00261    if (res) {
00262       ast_cli(fd, "Database entry not found.\n");
00263    } else {
00264       ast_cli(fd, "Value: %s\n", tmp);
00265    }
00266    return RESULT_SUCCESS;
00267 }

static int database_put ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 240 of file db.c.

References ast_cli(), ast_db_put(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00241 {
00242    int res;
00243    if (argc != 5)
00244       return RESULT_SHOWUSAGE;
00245    res = ast_db_put(argv[2], argv[3], argv[4]);
00246    if (res)  {
00247       ast_cli(fd, "Failed to update entry\n");
00248    } else {
00249       ast_cli(fd, "Updated database successfully\n");
00250    }
00251    return RESULT_SUCCESS;
00252 }

static int database_show ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 301 of file db.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), dbinit(), key(), keymatch(), keys, prefix, RESULT_SHOWUSAGE, and RESULT_SUCCESS.

00302 {
00303    char prefix[256];
00304    DBT key, data;
00305    char *keys, *values;
00306    int res;
00307    int pass;
00308 
00309    if (argc == 4) {
00310       /* Family and key tree */
00311       snprintf(prefix, sizeof(prefix), "/%s/%s", argv[2], argv[3]);
00312    } else if (argc == 3) {
00313       /* Family only */
00314       snprintf(prefix, sizeof(prefix), "/%s", argv[2]);
00315    } else if (argc == 2) {
00316       /* Neither */
00317       prefix[0] = '\0';
00318    } else {
00319       return RESULT_SHOWUSAGE;
00320    }
00321    ast_mutex_lock(&dblock);
00322    if (dbinit()) {
00323       ast_mutex_unlock(&dblock);
00324       ast_cli(fd, "Database unavailable\n");
00325       return RESULT_SUCCESS;  
00326    }
00327    memset(&key, 0, sizeof(key));
00328    memset(&data, 0, sizeof(data));
00329    pass = 0;
00330    while (!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
00331       if (key.size) {
00332          keys = key.data;
00333          keys[key.size - 1] = '\0';
00334       } else {
00335          keys = "<bad key>";
00336       }
00337       if (data.size) {
00338          values = data.data;
00339          values[data.size - 1]='\0';
00340       } else {
00341          values = "<bad value>";
00342       }
00343       if (keymatch(keys, prefix)) {
00344             ast_cli(fd, "%-50s: %-25s\n", keys, values);
00345       }
00346    }
00347    ast_mutex_unlock(&dblock);
00348    return RESULT_SUCCESS;  
00349 }

static int database_showkey ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 351 of file db.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), dbinit(), key(), keys, RESULT_SHOWUSAGE, RESULT_SUCCESS, and subkeymatch().

00352 {
00353    char suffix[256];
00354    DBT key, data;
00355    char *keys, *values;
00356    int res;
00357    int pass;
00358 
00359    if (argc == 3) {
00360       /* Key only */
00361       snprintf(suffix, sizeof(suffix), "/%s", argv[2]);
00362    } else {
00363       return RESULT_SHOWUSAGE;
00364    }
00365    ast_mutex_lock(&dblock);
00366    if (dbinit()) {
00367       ast_mutex_unlock(&dblock);
00368       ast_cli(fd, "Database unavailable\n");
00369       return RESULT_SUCCESS;  
00370    }
00371    memset(&key, 0, sizeof(key));
00372    memset(&data, 0, sizeof(data));
00373    pass = 0;
00374    while (!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
00375       if (key.size) {
00376          keys = key.data;
00377          keys[key.size - 1] = '\0';
00378       } else {
00379          keys = "<bad key>";
00380       }
00381       if (data.size) {
00382          values = data.data;
00383          values[data.size - 1]='\0';
00384       } else {
00385          values = "<bad value>";
00386       }
00387       if (subkeymatch(keys, suffix)) {
00388             ast_cli(fd, "%-50s: %-25s\n", keys, values);
00389       }
00390    }
00391    ast_mutex_unlock(&dblock);
00392    return RESULT_SUCCESS;  
00393 }

static int dbinit ( void   )  [static]

Definition at line 63 of file db.c.

References ast_config_AST_DB, ast_log(), and LOG_WARNING.

Referenced by ast_db_del(), ast_db_deltree(), ast_db_get(), ast_db_gettree(), ast_db_put(), astdb_init(), database_show(), and database_showkey().

00064 {
00065    if (!astdb && !(astdb = dbopen((char *)ast_config_AST_DB, O_CREAT | O_RDWR, 0664, DB_BTREE, NULL))) {
00066       ast_log(LOG_WARNING, "Unable to open Asterisk database\n");
00067       return -1;
00068    }
00069    return 0;
00070 }

static int keymatch ( const char *  key,
const char *  prefix 
) [inline, static]

Definition at line 73 of file db.c.

Referenced by ast_db_deltree(), ast_db_gettree(), and database_show().

00074 {
00075    int preflen = strlen(prefix);
00076    if (!preflen)
00077       return 1;
00078    if (!strcasecmp(key, prefix))
00079       return 1;
00080    if ((strlen(key) > preflen) && !strncasecmp(key, prefix, preflen)) {
00081       if (key[preflen] == '/')
00082          return 1;
00083    }
00084    return 0;
00085 }

static int manager_dbget ( struct mansession s,
const struct message m 
) [static]

Definition at line 551 of file db.c.

References ast_db_get(), ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_ack(), astman_send_error(), key(), and s.

Referenced by astdb_init().

00552 {
00553    const char *id = astman_get_header(m,"ActionID");
00554    char idText[256] = "";
00555    const char *family = astman_get_header(m, "Family");
00556    const char *key = astman_get_header(m, "Key");
00557    char tmp[256];
00558    int res;
00559 
00560    if (ast_strlen_zero(family)) {
00561       astman_send_error(s, m, "No family specified.");
00562       return 0;
00563    }
00564    if (ast_strlen_zero(key)) {
00565       astman_send_error(s, m, "No key specified.");
00566       return 0;
00567    }
00568 
00569    if (!ast_strlen_zero(id))
00570       snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id);
00571 
00572    res = ast_db_get(family, key, tmp, sizeof(tmp));
00573    if (res) {
00574       astman_send_error(s, m, "Database entry not found");
00575    } else {
00576       astman_send_ack(s, m, "Result will follow");
00577       astman_append(s, "Event: DBGetResponse\r\n"
00578             "Family: %s\r\n"
00579             "Key: %s\r\n"
00580             "Val: %s\r\n"
00581             "%s"
00582             "\r\n",
00583             family, key, tmp, idText);
00584    }
00585    return 0;
00586 }

static int manager_dbput ( struct mansession s,
const struct message m 
) [static]

Definition at line 522 of file db.c.

References ast_db_put(), ast_strlen_zero(), astman_get_header(), astman_send_ack(), astman_send_error(), key(), and s.

Referenced by astdb_init().

00523 {
00524    const char *family = astman_get_header(m, "Family");
00525    const char *key = astman_get_header(m, "Key");
00526    const char *val = astman_get_header(m, "Val");
00527    int res;
00528 
00529    if (ast_strlen_zero(family)) {
00530       astman_send_error(s, m, "No family specified");
00531       return 0;
00532    }
00533    if (ast_strlen_zero(key)) {
00534       astman_send_error(s, m, "No key specified");
00535       return 0;
00536    }
00537    if (ast_strlen_zero(val)) {
00538       astman_send_error(s, m, "No val specified");
00539       return 0;
00540    }
00541 
00542    res = ast_db_put(family, key, (char *) val);
00543    if (res) {
00544       astman_send_error(s, m, "Failed to update entry");
00545    } else {
00546       astman_send_ack(s, m, "Updated database successfully");
00547    }
00548    return 0;
00549 }

static int subkeymatch ( const char *  key,
const char *  suffix 
) [inline, static]

Definition at line 87 of file db.c.

Referenced by database_showkey().

00088 {
00089    int suffixlen = strlen(suffix);
00090    if (suffixlen) {
00091       const char *subkey = key + strlen(key) - suffixlen;
00092       if (subkey < key)
00093          return 0;
00094       if (!strcasecmp(subkey, suffix))
00095          return 1;
00096    }
00097    return 0;
00098 }


Variable Documentation

DB* astdb [static]

Definition at line 60 of file db.c.

struct ast_cli_entry cli_database[]

Definition at line 496 of file db.c.

Referenced by astdb_init().

char database_del_usage[] [static]

Initial value:

"Usage: database del <family> <key>\n"
"       Deletes an entry in the Asterisk database for a given\n"
"family and key.\n"

Definition at line 486 of file db.c.

char database_deltree_usage[] [static]

Initial value:

"Usage: database deltree <family> [keytree]\n"
"       Deletes a family or specific keytree within a family\n"
"in the Asterisk database.\n"

Definition at line 491 of file db.c.

char database_get_usage[] [static]

Initial value:

"Usage: database get <family> <key>\n"
"       Retrieves an entry in the Asterisk database for a given\n"
"family and key.\n"

Definition at line 481 of file db.c.

char database_put_usage[] [static]

Initial value:

"Usage: database put <family> <key> <value>\n"
"       Adds or updates an entry in the Asterisk database for\n"
"a given family, key, and value.\n"

Definition at line 476 of file db.c.

char database_show_usage[] [static]

Initial value:

"Usage: database show [family [keytree]]\n"
"       Shows Asterisk database contents, optionally restricted\n"
"to a given family, or family and keytree.\n"

Definition at line 467 of file db.c.

char database_showkey_usage[] [static]

Initial value:

"Usage: database showkey <keytree>\n"
"       Shows Asterisk database contents, restricted to a given key.\n"

Definition at line 472 of file db.c.


Generated on Mon May 14 04:48:18 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1