28#ifndef DOXYGEN_SHOULD_SKIP_THIS
33#include "git-revision.h"
43#define CHECK_OPEN_RECORD 1
138 while (msg != NULL) {
139 printf(
"db_err_msg: %p, next %p, type %d, file \'%s:%d\', function \'%s\': %s\n", msg, msg->
next, msg->
message_type, msg->
filename.c_str(), msg->
line, msg->
routine.c_str(), msg->
text.c_str());
144void db_msg(
db_err_msg** msgp,
INT message_type,
const char *filename,
INT line,
const char *routine,
const char *format, ...)
153 va_start(argptr, format);
159 const char* s =
"!db_msg too long!";
184 while (m->
next != NULL) {
187 assert(m->
next == NULL);
201 printf(
"db_flush_msg: %p\n", msg);
205 while (msg != NULL) {
241 assert(size ==
sizeof(
KEY) || size ==
sizeof(
KEYLIST));
258 bool have_good_block =
false;
266 if (pfree->
size >= size) {
267 have_good_block =
true;
271 int remaining = pfree->
size - size;
272 if ((remaining == 0) || (remaining >= (int)
ALIGN8(
sizeof(
KEYLIST))))
283 if (pass == 1 && have_good_block) {
300 if (pfree == pprev) {
308 assert(pfree->
size >= size);
314 if (size < pfree->size) {
348 assert((
void*)pfound != (
void*)pheader);
350 memset(pfound, 0, size);
363 assert(address != pheader);
372 memset(address, 0, size);
385 cm_msg(
MERROR,
"free_key",
"database is corrupted: pprev=%p, pprev->next_free=%d", pprev, pprev->
next_free);
403 memset(pnext, 0, pnext->
size);
411 memset(pfree, 0, pfree->
size);
464 if (pfree->
size >= size) {
483 if (pfree == pprev) {
491 assert(pfound != NULL);
492 assert(size <= pfound->size);
496 if (size < pfree->size) {
523 assert((
void*)pfound != (
void*)pheader);
526 memset(pfound, 0, size);
537 assert(address != pheader);
550 memset(address, 0, size);
570 while (pprev->
next_free < pfree_offset) {
577 cm_msg(
MERROR,
"free_data",
"database is corrupted: pprev=%p, pprev->next_free=%d in free_data(%p,%p,%d) from %s", pprev, pprev->
next_free, pheader, address, size, caller);
597 memset(pnext, 0, pnext->
size);
606 memset(pfree, 0, pfree->
size);
619 tmp = malloc(old_size);
621 cm_msg(
MERROR,
"realloc_data",
"cannot malloc(%d), called from %s", old_size, caller);
625 memcpy(tmp, address, old_size);
630 cm_msg(
MERROR,
"realloc_data",
"cannot free_data(%p, %d), called from %s", address, old_size, caller);
640 cm_msg(
MERROR,
"realloc_data",
"cannot malloc_data(%d), called from %s", new_size, caller);
645 memcpy(pnew, tmp, old_size < new_size ? old_size : new_size);
659 static char *
str = NULL;
667 str = (
char *) malloc(
j);
669 str = (
char *) realloc(
str,
j);
689 for (
int i = 0;
list[
i];
i++) {
721 keyfreelist->clear();
724 db_msg(msg,
MERROR,
"db_get_key_free_list",
"Error: database corruption, invalid pheader->first_free_key %d", pheader->
first_free_key);
733 ks.
hkey = (
char*)pfree - (
char*)pheader;
736 keyfreelist->push_back(ks);
743 db_msg(msg,
MERROR,
"db_get_key_free_list",
"Error: database corruption, invalid pfree->next_free %d", pfree->
next_free);
750 db_msg(msg,
MERROR,
"db_get_key_free_list",
"Error: database corruption, free list is too long: %zu", keyfreelist->size());
759 datafreelist->clear();
762 db_msg(msg,
MERROR,
"db_get_data_free_list",
"Error: database corruption, invalid pheader->first_free_data %d", pheader->
first_free_data);
771 ks.
hdata = (
char*)pfree - (
char*)pheader;
774 datafreelist->push_back(ks);
781 db_msg(msg,
MERROR,
"db_get_key_free_list",
"Error: database corruption, invalid pfree->next_free %d", pfree->
next_free);
788 db_msg(msg,
MERROR,
"db_get_data_free_list",
"Error: database corruption, free list is too long: %zu", datafreelist->size());
795 std::string* pbuf = (std::string*)
info;
803 for (
int i = 0;
i < level;
i++)
822 return "(Cannot lock ODB)";
831 size_t odb_data_start = odb_key_end;
832 size_t odb_data_end = odb_data_start + pheader->
data_size;
835 buf +=
msprintf(
"Key area: %9zu - %9zu, size %9d bytes\n", odb_key_start, odb_key_end, pheader->
key_size);
836 buf +=
msprintf(
"Data area: %9zu - %9zu, size %9d bytes\n", odb_data_start, odb_data_end, pheader->
data_size);
838 buf +=
"Key free list:\n";
845 size_t total_size_key = 0;
848 buf +=
"ODB key free list is corrupted, see messages!\n\n";
851 for (
size_t i=0;
i<keyfreelist.size();
i++) {
852 buf +=
msprintf(
"Free block %3zu at %9d, size %9zu, next %9d\n",
856 keyfreelist[
i].next_free);
857 total_size_key += keyfreelist[
i].skey;
861 buf +=
msprintf(
"Free Key area: %zu bytes out of %d bytes\n", total_size_key, pheader->
key_size);
863 buf +=
"Data free list:\n";
870 size_t total_size_data = 0;
871 size_t biggest_size_data = 0;
874 buf +=
"ODB data free list is corrupted, see messages!\n\n";
877 for (
size_t i=0;
i<datafreelist.size();
i++) {
878 buf +=
msprintf(
"Free block %3zu at %9d, size %9zu, next %9d\n",
880 datafreelist[
i].hdata,
881 datafreelist[
i].sdata,
882 datafreelist[
i].next_free);
883 total_size_data += datafreelist[
i].sdata;
884 if (datafreelist[
i].sdata > biggest_size_data)
885 biggest_size_data = datafreelist[
i].sdata;
889 buf +=
msprintf(
"Free Data area: %zu bytes out of %d bytes\n", total_size_data, pheader->
data_size);
891 buf +=
msprintf(
"Biggest Data area free block: %zu bytes\n", biggest_size_data);
893 buf +=
msprintf(
"Free: %zu (%1.1lf%%) keylist, %zu (%1.1lf%%) data\n",
895 100 * (
double) total_size_key / pheader->
key_size,
896 total_size_data, 100 * (
double) total_size_data / pheader->
data_size);
899 const KEY* proot =
db_get_pkey(pheader, 0, 0,
"db_show_mem", &msg);
904 buf +=
" Key Data Size\n";
905 buf +=
"-----------------------------\n";
907 buf +=
"-----------------------------\n";
908 buf +=
" Key Data Size\n";
913 buf +=
msprintf(
"Total ODB size: %d (0x%08X) Bytes, %lg MBytes\n",
948 for (
const auto e : keyfreelist) {
949 *pkey_size +=
e.skey;
956 for (
const auto e : datafreelist) {
957 *pdata_size +=
e.sdata;
958 if (
e.sdata > *pdata_biggest)
959 *pdata_biggest =
e.sdata;
994 db_msg(msg,
MERROR,
"db_validate_name",
"Invalid name passed to %s: should not be NULL", caller_name);
998 size_t len = strlen(
name);
1001 db_msg(msg,
MERROR,
"db_validate_name",
"Invalid name passed to %s: should not be an empty string", caller_name);
1005 if (strchr(
name,
'[')) {
1006 db_msg(msg,
MERROR,
"db_validate_name",
"Invalid name \"%s\" passed to %s: should not contain \"[\"",
name, caller_name);
1010 if (
name[0] ==
' ') {
1011 db_msg(msg,
MERROR,
"db_validate_name",
"Invalid name \"%s\" passed to %s: should not start with a space",
name, caller_name);
1015 if (
name[len-1] ==
' ') {
1016 db_msg(msg,
MERROR,
"db_validate_name",
"Invalid name \"%s\" passed to %s: should not end with a space",
name, caller_name);
1020 if (strchr(
name,
']')) {
1021 db_msg(msg,
MERROR,
"db_validate_name",
"Invalid name \"%s\" passed to %s: should not contain \"[\"",
name, caller_name);
1026 db_msg(msg,
MERROR,
"db_validate_name",
"Invalid name \"%s\" passed to %s: invalid unicode UTF-8 encoding",
name, caller_name);
1031 if (strchr(
name,
'/')) {
1032 db_msg(msg,
MERROR,
"db_validate_name",
"Invalid name \"%s\" passed to %s: should not contain \"/\"",
name, caller_name);
1037 db_msg(msg,
MERROR,
"db_validate_name",
"Invalid name \"%s\" passed to %s: length %d should be less than %d bytes",
name, caller_name, (
int)strlen(
name),
NAME_LENGTH);
1091 hKey_is_root_key =
TRUE;
1109 const KEY* pkey = (
const KEY *) ((
char *) pheader +
hKey);
1113 if (hKey_is_root_key) {
1114 db_msg(msg,
MERROR, caller,
"db_get_pkey: root_key hkey %d invalid key type %d, database root directory is corrupted",
hKey, tid);
1120 db_msg(msg,
MERROR, caller,
"db_get_pkey: hkey %d path \"%s\" invalid key type %d",
hKey, path.c_str(), tid);
1127 if (pkey->
name[0] == 0) {
1129 db_msg(msg,
MERROR, caller,
"db_get_pkey: hkey %d path \"%s\" invalid name \"%s\" is empty",
hKey, path.c_str(), pkey->
name);
1142 db_msg(msg,
MERROR, caller,
"db_get_pkeylist: path \"%s\" unexpected call to db_get_pkeylist(), not a subdirectory, pkey->type %d", path.c_str(), pkey->
type);
1148 db_msg(msg,
MERROR, caller,
"Invalid pkey->data %d at path \"%s\"", pkey->
data, path.c_str());
1161 if (!kludge_repair) {
1163 db_msg(msg,
MERROR, caller,
"Invalid pkeylist->first_key %d should be non zero for num_keys %d at \"%s\"", pkeylist->
first_key, pkeylist->
num_keys, path.c_str());
1172 db_msg(msg,
MERROR, caller,
"Repaired invalid num_keys %d when pkeylist->first_key is zero at \"%s\"", pkeylist->
num_keys, path.c_str());
1173 ((
KEYLIST*)pkeylist)->num_keys = 0;
1214 db_msg(msg,
MERROR,
"db_enum_first_locked",
"path \"%s\" tid %d is not a directory", path.c_str(), pkey->
type);
1258 if (*((
char *) pheader + pkey->
data) ==
'/') {
1272 path = xpath.c_str();
1275 printf(
"path \"%s\", parenthkey %d, hkey %d, name \"%s\", type %d, parent %d, data %d, total_size %d", path, parenthkeylist, hkey, pkey->
name, pkey->
type, pkey->
parent_keylist, pkey->
data, pkey->
total_size);
1283 printf(
", pkeylist parent %d, num_keys %d, first_key %d", pkeylist->
parent, pkeylist->
num_keys, pkeylist->
first_key);
1291 const KEY *pkey =
db_get_pkey(pheader, hkey, NULL,
"db_print_key", NULL);
1297 db_print_pkey(pheader, pkey, recurse, path, parenthkeylist);
1306 db_msg(msg,
MERROR,
"db_validate_and_repair_key_wlocked",
"Max ODB depth level %d exceeded at \"%s\"",
MAX_ODB_PATH, path);
1319 db_msg(msg,
MERROR,
"db_validate_key",
"hkey %d, path \"%s\", invalid hkey", hkey, path);
1325 db_msg(msg,
MERROR,
"db_validate_key",
"hkey %d, path \"%s\", name \"%s\", invalid key type %d", hkey, path, pkey->
name, pkey->
type);
1333 sprintf(newname,
"%p", pkey);
1334 db_msg(msg,
MERROR,
"db_validate_key",
"hkey %d, path \"%s\": invalid name \"%s\" replaced with \"%s\"", hkey, path, pkey->
name, newname);
1335 mstrlcpy(pkey->
name, newname,
sizeof(pkey->
name));
1342 db_msg(msg,
MERROR,
"db_validate_key",
"hkey %d, path \"%s\", name \"%s\", invalid parent_keylist %d should be %d", hkey, path, pkey->
name, pkey->
parent_keylist, parenthkeylist);
1347 db_msg(msg,
MERROR,
"db_validate_key",
"hkey %d, path \"%s\", invalid data offset 0x%08X is invalid", hkey, path, pkey->
data - (
int)
sizeof(
DATABASE_HEADER));
1353 db_msg(msg,
MERROR,
"db_validate_key",
"hkey %d, path \"%s\", invalid pkey->total_size %d", hkey, path, pkey->
total_size);
1358 db_msg(msg,
MERROR,
"db_validate_key",
"hkey %d, path \"%s\", invalid pkey->item_size: %d", hkey, path, pkey->
item_size);
1363 db_msg(msg,
MERROR,
"db_validate_key",
"hkey %d, path \"%s\", invalid pkey->num_values: %d", hkey, path, pkey->
num_values);
1369 db_msg(msg,
MERROR,
"db_validate_key",
"hkey %d, path \"%s\", corrected pkey->total_size from %d to %d*%d=%d", hkey, path, pkey->
total_size, pkey->
item_size, pkey->
num_values, pkey->
item_size * pkey->
num_values);
1376 db_msg(msg,
MERROR,
"db_validate_key",
"hkey %d, path \"%s\", pkey->data is zero, corrected pkey->num_values %d and pkey->total_size %d to be zero, should be zero", hkey, path, pkey->
num_values, pkey->
total_size);
1383 const char* s = (
char*)pheader + pkey->
data;
1385 db_msg(msg,
MERROR,
"db_validate_key",
"hkey %d, path \"%s\" is not a valid UTF-8 Unicode string", hkey, path);
1392 bool good_link =
true;
1401 db_msg(msg,
MERROR,
"db_validate_key",
"hkey %d, path \"%s\", TID_LINK is an empty link", hkey, path);
1421 const char* link = (
char*)pheader + pkey->
data;
1422 size_t link_len = strlen(link);
1424 if (link_len <= 2) {
1425 db_msg(msg,
MERROR,
"db_validate_key",
"hkey %d, path \"%s\", TID_LINK is an empty link", hkey, path);
1430 size_t path_len = strlen(path);
1431 if (link_len == path_len) {
1434 db_msg(msg,
MERROR,
"db_validate_key",
"hkey %d, path \"%s\", TID_LINK to \"%s\" is a link to itself", hkey, path, link);
1439 }
else if (link_len < path_len) {
1442 memcpy(tmp, path, link_len);
1445 db_msg(msg,
MERROR,
"db_validate_key",
"hkey %d, path \"%s\", TID_LINK to \"%s\" is a loop", hkey, path, link);
1457 db_msg(msg,
MERROR,
"db_validate_key",
"hkey %d, path \"%s\", invalid pkey->access_mode %d", hkey, path, pkey->
access_mode);
1464 db_msg(msg,
MERROR,
"db_validate_key",
"hkey %d, path \"%s\", invalid pkey->last_written time %d", hkey, path, pkey->
last_written);
1474 kv.
skey =
sizeof(*pkey);
1477 keylist->push_back(kv);
1482 kv1.
skey =
sizeof(*pkey);
1485 keylist->push_back(kv1);
1493 keylist->push_back(kv2);
1498 bool pkeylist_ok =
true;
1503 db_msg(msg,
MERROR,
"db_validate_key",
"hkey %d, path \"%s\", invalid pkey->data %d", hkey, path, pkey->
data);
1506 if (pkeylist->
parent != hkey) {
1507 db_msg(msg,
MERROR,
"db_validate_key",
"hkey %d, path \"%s\", TID_KEY invalid pkeylist->parent %d is not hkey %d", hkey, path, pkeylist->
parent, hkey);
1509 pkeylist_ok =
false;
1513 db_msg(msg,
MERROR,
"db_validate_key",
"hkey %d, path \"%s\", TID_KEY invalid pkeylist->num_keys %d", hkey, path, pkeylist->
num_keys);
1515 pkeylist_ok =
false;
1521 db_msg(msg,
MERROR,
"db_validate_key",
"hkey %d, path \"%s\", TID_KEY invalid pkeylist->first_key %d", hkey, path, pkeylist->
first_key);
1523 pkeylist_ok =
false;
1532 while (subhkey != 0) {
1533 KEY* subpkey = (
KEY*)
db_get_pkey(pheader, subhkey, NULL,
"db_validate_key", msg);
1535 db_msg(msg,
MERROR,
"db_validate_key",
"hkey %d, path \"%s\", TID_KEY invalid subhkey %d", hkey, path, subhkey);
1536 pkeylist_ok =
false;
1544 buf += subpkey->
name;
1557 db_msg(msg,
MERROR,
"db_validate_key",
"hkey %d, path \"%s\", repaired TID_KEY mismatch of pkeylist->num_keys %d against key chain length %d", hkey, path, pkeylist->
num_keys,
count);
1560 pkeylist_ok =
false;
1581 cm_msg(
MERROR,
"db_get_my_client_locked",
"My client index %d in ODB is invalid: out of range 0..%d. Maybe this client was removed by a timeout, see midas.log. Cannot continue, aborting...", idx, pheader->
max_client_index-1);
1588 if (pclient->
name[0] == 0) {
1589 cm_msg(
MERROR,
"db_get_my_client_locked",
"My client index %d in ODB is invalid: client name is blank. Maybe this client was removed by a timeout, see midas.log. Cannot continue, aborting...", idx);
1596 if (pclient->
pid != pid) {
1597 cm_msg(
MERROR,
"db_get_my_client_locked",
"My client index %d in ODB is invalid: pid mismatch, my pid is %d, but ODB has %d. Maybe this client was removed by a timeout, see midas.log. Cannot continue, aborting...", idx, pid, pclient->
pid);
1622#define S(x) printf("assert(sizeof(%-20s) == %6d);\n", #x, (int)sizeof(x))
1670 printf(
"EQUIPMENT_INFO offset of event_id: %d\n", (
int)((
char*)&
eq.event_id - (
char*)&
eq));
1671 printf(
"EQUIPMENT_INFO offset of eq_type: %d\n", (
int)((
char*)&
eq.eq_type - (
char*)&
eq));
1672 printf(
"EQUIPMENT_INFO offset of event_limit: %d\n", (
int)((
char*)&
eq.event_limit - (
char*)&
eq));
1673 printf(
"EQUIPMENT_INFO offset of num_subevents: %d\n", (
int)((
char*)&
eq.num_subevents - (
char*)&
eq));
1674 printf(
"EQUIPMENT_INFO offset of status: %d\n", (
int)((
char*)&
eq.status - (
char*)&
eq));
1675 printf(
"EQUIPMENT_INFO offset of hidden: %d\n", (
int)((
char*)&
eq.hidden - (
char*)&
eq));
1678 assert(
sizeof(
UINT8) == 1);
1679 assert(
sizeof(
INT8) == 1);
1680 assert(
sizeof(
UINT16) == 2);
1681 assert(
sizeof(
INT16) == 2);
1682 assert(
sizeof(
UINT32) == 4);
1683 assert(
sizeof(
INT32) == 4);
1684 assert(
sizeof(
UINT64) == 8);
1685 assert(
sizeof(
INT64) == 8);
1694 assert(
sizeof(
TAG) == 40);
1695 assert(
sizeof(
KEY) == 68);
1696 assert(
sizeof(
KEYLIST) == 12);
1704 assert(
sizeof(
BANK) == 8);
1705 assert(
sizeof(
BANK32) == 12);
1706 assert(
sizeof(
BANK32A) == 16);
1709 assert(
sizeof(
ALARM) == 460);
1767 printf(
"%s, notify_count %d, found %d, our count %d\n", path, pkey->
notify_count, found,
count);
1771 db_msg(msg,
MINFO,
"db_update_open_record",
"Added missing open record flag to \"%s\"", path.c_str());
1778 db_msg(msg,
MINFO,
"db_update_open_record",
"Removed open record flag from \"%s\"", path.c_str());
1785 db_msg(msg,
MERROR,
"db_update_open_record",
"Cannot remove exclusive access mode from \"%s\", db_set_mode() status %d", path.c_str(),
status);
1788 db_msg(msg,
MINFO,
"db_update_open_record",
"Removed exclusive access mode from \"%s\"", path.c_str());
1816 assert(uor.
hkeys != NULL);
1817 assert(uor.
counts != NULL);
1818 assert(uor.
modes != NULL);
1845 printf(
"index %d, handle %d, count %d, access mode %d\n",
i, uor.
hkeys[
i], uor.
counts[
i], uor.
modes[
i]);
1869 bool enable_repair =
false;
1874 if (getenv(
"MIDAS_ODB_REPAIR_FREE_LIST")) {
1875 db_msg(msg,
MINFO,
"db_validate_db",
"ODB free list repair is enabled by env.variable");
1879 db_msg(msg,
MERROR,
"db_validate_db",
"ODB key free list repair is disabled. To enable repair, \"export MIDAS_ODB_REPAIR_FREE_LIST=1\" and try again");
1890 for (
size_t i=0;
i<keylist.size();
i++) {
1893 gap = keylist[
i].hkey - (keylist[
i-1].hkey +
ALIGN8(keylist[
i-1].skey));
1894 printf(
"keylist[%zu] type %2d, hkey %7d, key size %3zu, hdata %9d, data size %9zu, key gap %zu\n",
i, keylist[
i].
type, keylist[
i].hkey, keylist[
i].skey, keylist[
i].hdata, keylist[
i].sdata, gap);
1901 std::vector<keylist_struct> keyfree;
1905 for (
size_t i=1;
i<keylist.size();
i++) {
1907 size_t hthis = keylist[
i-1].hkey;
1908 size_t sthis =
ALIGN8(keylist[
i-1].skey);
1909 size_t hend = hthis + sthis;
1913 if (hthis == odb_key_start) {
1919 ds.
hkey = odb_key_start;
1920 ds.
skey = hthis - odb_key_start;
1921 keyfree.push_back(ds);
1925 size_t hnext = keylist[
i].hkey;
1927 if (hnext == hend) {
1936 ds.
skey = hnext - hend;
1937 keyfree.push_back(ds);
1943 size_t overlap = hend - hnext;
1950 db_msg(msg,
MERROR,
"db_validate_key_area",
"Error: ODB key area is corrupted, \"%s\" (%zu+%zu) overlaps \"%s\" (%zu) by %zu bytes, cannot repair", this_path.c_str(), hthis, sthis, next_path.c_str(), hnext, overlap);
1955 size_t ilast = keylist.size()-1;
1956 HNDLE last_used = keylist[ilast].hkey +
ALIGN8(keylist[ilast].skey);
1958 ds.
hkey = last_used;
1959 ds.
skey = odb_key_end - last_used;
1962 keyfree.push_back(ds);
1968 for (
size_t i=0;
i<keyfree.size();
i++) {
1969 printf(
"keyfree[%zu] hkey %9d, key size %9zu\n",
i, keyfree[
i].hkey, keyfree[
i].skey);
1973 for (
size_t i=0;
i<keyfreelist.size();
i++) {
1974 printf(
"keyfreelist[%zu] hkey %9d, key size %9zu\n",
i, keyfreelist[
i].hkey, keyfreelist[
i].skey);
1978 bool needs_repair =
false;
1980 size_t key_check_size = keyfree.size();
1982 if (keyfree.size() != keyfreelist.size()) {
1983 db_msg(msg,
MERROR,
"db_validate_key_area",
"Error: ODB key free list is corrupted, key free list length %zu should be %zu", keyfreelist.size(), keyfree.size());
1985 needs_repair =
true;
1986 key_check_size =
MIN(keyfree.size(), keyfreelist.size());
1989 for (
size_t i=0;
i<key_check_size;
i++) {
1990 if (keyfree[
i].hkey != keyfreelist[
i].hkey) {
1991 db_msg(msg,
MERROR,
"db_validate_key_area",
"Error: ODB key free list is corrupted, entry %zu mismatch %d should be %d",
i, keyfreelist[
i].hkey, keyfree[
i].hkey);
1993 needs_repair =
true;
1995 }
else if (keyfree[
i].skey != keyfreelist[
i].skey) {
1996 db_msg(msg,
MERROR,
"db_validate_key_area",
"Error: ODB key free list is corrupted, entry %zu size mismatch %zu should be %zu",
i, keyfreelist[
i].skey, keyfree[
i].skey);
1998 needs_repair =
true;
2006 db_msg(msg,
MINFO,
"db_validate_key_area",
"Rewriting corrupted ODB key free list");
2008 for (
size_t i=0;
i<keyfree.size();
i++) {
2009 HNDLE hh = keyfree[
i].hkey;
2010 size_t ss = keyfree[
i].skey;
2012 if (
i<keyfree.size()-1) {
2013 hnext = keyfree[
i+1].hkey;
2023 if (keyfree.size() > 0)
2038 for (
size_t i=0;
i<keylist.size();
i++) {
2041 gap = keylist[
i].hdata - (keylist[
i-1].hdata +
ALIGN8(keylist[
i-1].sdata));
2042 printf(
"keylist[%zu] type %2d, hkey %7d, key size %3zu, hdata %9d, data size %9zu, data gap %zu\n",
i, keylist[
i].
type, keylist[
i].hkey, keylist[
i].skey, keylist[
i].hdata, keylist[
i].sdata, gap);
2049 std::vector<keylist_struct> datafree;
2053 HNDLE last_used = 0;
2055 for (
size_t i=1;
i<keylist.size();
i++) {
2057 if (keylist[
i-1].hdata == 0)
2060 if (keylist[
i].hdata == 0)
2063 size_t hthis = keylist[
i-1].hdata;
2064 size_t sthis =
ALIGN8(keylist[
i-1].sdata);
2065 size_t hend = hthis + sthis;
2067 last_used = keylist[
i].hdata +
ALIGN8(keylist[
i].sdata);
2071 if (hthis == odb_data_start) {
2077 ds.
hdata = odb_data_start;
2078 ds.
sdata = hthis - odb_data_start;
2079 datafree.push_back(ds);
2083 size_t hnext = keylist[
i].hdata;
2085 if (hnext == hend) {
2094 ds.
sdata = hnext - hend;
2095 datafree.push_back(ds);
2101 size_t overlap = hend - hnext;
2108 db_msg(msg,
MERROR,
"db_validate_data_area",
"Error: ODB data area is corrupted, \"%s\" (%zu+%zu) overlaps \"%s\" (%zu) by %zu bytes", this_path.c_str(), hthis, sthis, next_path.c_str(), hnext, overlap);
2112 db_msg(msg,
MERROR,
"db_validate_data_area",
"Error: ODB data area is corrupted, clearing overlapping data of \"%s\"", this_path.c_str());
2113 KEY* pkey = (
KEY*)
db_get_pkey(pheader, keylist[
i-1].hkey, NULL,
"db_validate_data_area", msg);
2128 if (last_used == 0) {
2129 last_used = odb_data_start;
2133 ds.
hdata = last_used;
2134 ds.
sdata = odb_data_end - last_used;
2135 if (ds.
sdata != 0) {
2136 datafree.push_back(ds);
2142 for (
size_t i=0;
i<datafree.size();
i++) {
2143 printf(
"datafree[%zu] hdata %9d, data size %9zu\n",
i, datafree[
i].hdata, datafree[
i].sdata);
2147 for (
size_t i=0;
i<datafreelist.size();
i++) {
2148 printf(
"datafreelist[%zu] hdata %9d, data size %9zu\n",
i, datafreelist[
i].hdata, datafreelist[
i].sdata);
2152 bool needs_repair =
false;
2154 size_t data_check_size = datafree.size();
2156 if (datafree.size() != datafreelist.size()) {
2157 db_msg(msg,
MERROR,
"db_validate_data_area",
"Error: ODB data free list is corrupted, data free list length %zu should be %zu", datafreelist.size(), datafree.size());
2158 data_check_size =
MIN(datafree.size(), datafreelist.size());
2160 needs_repair =
true;
2163 for (
size_t i=0;
i<data_check_size;
i++) {
2164 if (datafree[
i].hdata != datafreelist[
i].hdata) {
2165 db_msg(msg,
MERROR,
"db_validate_data_area",
"Error: ODB data free list is corrupted, entry %zu mismatch %d should be %d",
i, datafreelist[
i].hdata, datafree[
i].hdata);
2167 needs_repair =
true;
2169 }
else if (datafree[
i].sdata != datafreelist[
i].sdata) {
2170 db_msg(msg,
MERROR,
"db_validate_data_area",
"Error: ODB data free list is corrupted, entry %zu size mismatch %zu should be %zu",
i, datafreelist[
i].sdata, datafree[
i].sdata);
2172 needs_repair =
true;
2180 db_msg(msg,
MINFO,
"db_validate_data_area",
"Rewriting corrupted ODB data free list");
2182 for (
size_t i=0;
i<datafree.size();
i++) {
2183 HNDLE hh = datafree[
i].hdata;
2184 size_t ss = datafree[
i].sdata;
2186 if (
i<datafree.size()-1) {
2187 hnext = datafree[
i+1].hdata;
2197 if (datafree.size() > 0)
2218 std::vector<keylist_struct> keyfreelist;
2222 int total_size_key = 0;
2224 for (
const auto e : keyfreelist) {
2225 total_size_key +=
e.skey;
2228 double key_ratio = ((double) (pheader->
key_size - total_size_key)) / ((
double) pheader->
key_size);
2230 if (key_ratio > 0.9)
2231 db_msg(msg,
MERROR,
"db_validate_db",
"Warning: database key area is %.0f%% full", key_ratio * 100.0);
2233 if (total_size_key > pheader->
key_size) {
2234 db_msg(msg,
MERROR,
"db_validate_db",
"Error: database corruption, total_size_key %d is bigger than pheader->key_size %d", total_size_key, pheader->
key_size);
2240 std::vector<keylist_struct> datafreelist;
2244 int total_size_data = 0;
2246 for (
const auto e : datafreelist) {
2247 total_size_data +=
e.sdata;
2250 double ratio_data = ((double) (pheader->
data_size - total_size_data)) / ((
double) pheader->
data_size);
2251 if (ratio_data > 0.9)
2252 db_msg(msg,
MERROR,
"db_validate_db",
"Warning: database data area is %.0f%% full", ratio_data * 100.0);
2254 if (total_size_data > pheader->
data_size) {
2255 db_msg(msg,
MERROR,
"db_validate_db",
"Error: database corruption, total_size_data %d is bigger than pheader->data_size 0x%08X", total_size_data, pheader->
data_size);
2270 if (!keylist.empty()) {
2272 for (
size_t i=0;
i<keylist.size();
i++) {
2273 keylist[
i].hsort = keylist[
i].hkey;
2276 std::sort(keylist.begin(), keylist.end());
2281 if (!keylist.empty()) {
2283 for (
size_t i=0;
i<keylist.size();
i++) {
2284 keylist[
i].hsort = keylist[
i].hdata;
2287 std::sort(keylist.begin(), keylist.end());
2293 db_msg(msg,
MERROR,
"db_validate_db",
"Error: ODB corruption detected, see previous messages");
2320#ifdef LOCAL_ROUTINES
2335 mstrlcpy(database_name, xdatabase_name,
NAME_LENGTH);
2337 int odb_size_limit = 100*1000*1000;
2338 if (database_size < 0 || database_size > odb_size_limit) {
2339 cm_msg(
MERROR,
"db_open_database",
"invalid database size: %d bytes. ODB size limit is %d bytes", database_size, odb_size_limit);
2344 cm_msg(
MERROR,
"db_open_database",
"client name \'%s\' is longer than %d characters", client_name,
NAME_LENGTH-1);
2348 if (strchr(client_name,
'/') != NULL) {
2349 cm_msg(
MERROR,
"db_open_database",
"client name \'%s\' should not contain the slash \'/\' character", client_name);
2400 void* shm_adr = NULL;
2401 size_t shm_size = 0;
2428 if (shm_created && pheader->
name[0] == 0) {
2432 strcpy(pheader->
name, database_name);
2457 strcpy(pkey->
name,
"root");
2483 cm_msg(
MERROR,
"db_open_database",
"Invalid database, shared memory size %d is smaller than database size %d (header: %d, key area: %d, data area: %d). Delete this shared memory (odbedit -R), create a new odb (odbinit) and reload it from the last odb save file.",
_database[handle].shm_size, (
int)
sizeof(
DATABASE_HEADER) + pheader->
key_size + pheader->
data_size, (
int)
sizeof(
DATABASE_HEADER), pheader->
key_size, pheader->
data_size);
2489 cm_msg(
MERROR,
"db_open_database",
"Invalid, incompatible or corrupted database: root key offset %d is invalid", pheader->
root_key);
2492 pkey = (
KEY*)((
char*)pheader + pheader->
root_key);
2495 cm_msg(
MERROR,
"db_open_database",
"Invalid, incompatible or corrupted database: root key type %d is not TID_KEY", pkey->
type);
2499 if (strcmp(pkey->
name,
"root") != 0) {
2500 cm_msg(
MERROR,
"db_open_database",
"Invalid, incompatible or corrupted database: root key name \"%s\" is not \"root\"", pkey->
name);
2515 cm_msg(
MERROR,
"db_open_database",
"Invalid, incompatible or corrupted database: root key is invalid");
2558 int num_clients = 0;
2559 int max_client_index = 0;
2564 max_client_index =
i + 1;
2579 mstrlcpy(client_name_tmp, pheader->
client[
i].
name,
sizeof(client_name_tmp));
2588 cm_msg(
MERROR,
"db_open_database",
"Removed ODB client \'%s\', index %d because process pid %d does not exists", client_name_tmp,
i, client_pid);
2602 cm_msg(
MERROR,
"db_open_database",
"maximum number of clients exceeded");
2618 pclient = &pheader->
client[
i];
2621 mstrlcpy(pclient->
name, client_name,
sizeof(pclient->
name));
2655 *
hDB = (handle + 1);
2662 cm_msg(
MERROR,
"db_open_database",
"Error: db_validate_open_records() status %d",
status);
2690#ifdef LOCAL_ROUTINES
2692 INT destroy_flag,
i,
j;
2696 cm_msg(
MERROR,
"db_close_database",
"invalid database handle %d",
hDB);
2710 cm_msg(
MERROR,
"db_close_database",
"database not attached");
2748 mstrlcpy(xname, pheader->
name,
sizeof(xname));
2798#ifndef DOXYGEN_SHOULD_SKIP_THIS
2825#ifdef LOCAL_ROUTINES
2828 uint32_t flush_period = 60;
2829 uint32_t last_flush = 0;
2832 cm_msg(
MERROR,
"db_flush_database",
"invalid database handle");
2837 size =
sizeof(flush_period);
2839 size =
sizeof(last_flush);
2845 cm_msg(
MERROR,
"db_flush_database",
"Cannot obtain key /System/Flush/Last flush");
2855 cm_msg(
MERROR,
"db_flush_database",
"invalid database handle");
2870 size =
sizeof(last_flush);
2874 if (
ss_time() > last_flush + flush_period) {
2922#ifdef LOCAL_ROUTINES
2958#ifdef LOCAL_ROUTINES
2961 cm_msg(
MERROR,
"db_set_client_name",
"invalid database handle %d",
hDB);
2969 mstrlcpy(pclient->
name, client_name,
sizeof(pclient->
name));
2990#ifdef LOCAL_ROUTINES
3001#ifdef LOCAL_ROUTINES
3006 cm_msg(
MERROR, caller,
"invalid database handle %d, aborting...",
hDB);
3016 if (check_attached && !pdb->
attached) {
3017 cm_msg(
MERROR, caller,
"invalid database handle %d, aborting...",
hDB);
3026 cm_msg(
MERROR,
"db_lock_database",
"database handle mismatch %d vs %d, aborting...",
hDB, pdb->
hDB);
3037 cm_msg(
MERROR,
"db_lock_database",
"cannot lock ODB mutex, timeout %d ms, status %d, aborting...", pdb->
timeout,
status);
3044 fprintf(stderr,
"db_lock_database: Detected recursive call to db_{lock,unlock}_database() while already inside db_{lock,unlock}_database(). Maybe this is a call from a signal handler. Cannot continue, aborting...\n");
3070 cm_msg(
MERROR,
"db_lock_database",
"cannot lock ODB semaphore, timeout %d ms, aborting...", pdb->
timeout);
3076 cm_msg(
MERROR,
"db_lock_database",
"cannot lock ODB semaphore, timeout %d ms, ss_semaphore_wait_for() status %d, aborting...", pdb->
timeout,
status);
3084#ifdef CHECK_LOCK_COUNT
3098 cm_msg(
MERROR,
"db_lock_database",
"cannot lock ODB, ss_shm_unprotect(TRUE,FALSE) failed with status %d, aborting...",
status);
3124 cm_msg(
MERROR,
"db_allow_write_locked",
"cannot write to ODB, ss_shm_unprotect(TRUE,TRUE) failed with status %d, aborting...",
status);
3145#ifdef LOCAL_ROUTINES
3148 cm_msg(
MERROR,
"db_unlock_database",
"invalid database handle %d",
hDB);
3163#ifdef LOCAL_ROUTINES
3167#ifdef CHECK_LOCK_COUNT
3176 fprintf(stderr,
"db_unlock_database: Detected recursive call to db_{lock,unlock}_database() while already inside db_{lock,unlock}_database(). Maybe this is a call from a signal handler. Cannot continue, aborting...\n");
3199 cm_msg(
MERROR,
"db_unlock_database",
"cannot unlock ODB, ss_shm_protect() failed with status %d, aborting...",
status);
3223#ifdef LOCAL_ROUTINES
3230 cm_msg(
MERROR,
"db_get_lock_cnt",
"invalid database handle %d, aborting...",
hDB);
3231 fprintf(stderr,
"db_get_lock_cnt: invalid database handle %d, aborting...\n",
hDB);
3245#ifdef LOCAL_ROUTINES
3252 cm_msg(
MERROR,
"db_set_lock_timeout",
"invalid database handle %d",
hDB);
3256 if (timeout_millisec > 0) {
3266#ifdef LOCAL_ROUTINES
3284 if (pdbclient->
pid == pid) {
3294 cm_msg(
MERROR,
"db_update_last_activity",
"Did not find this client in any database. Maybe this client was removed by a timeout, see midas.log. Cannot continue, aborting...");
3303#ifdef LOCAL_ROUTINES
3338#ifdef LOCAL_ROUTINES
3346 std::string
str =
msprintf(
"System/Clients/%0d", pid);
3373#ifdef LOCAL_ROUTINES
3375 cm_msg(
MERROR,
"db_delete_client_info",
"invalid database handle");
3380 cm_msg(
MERROR,
"db_delete_client_info",
"invalid database handle");
3408#ifdef LOCAL_ROUTINES
3426 if (wrong_interval) {
3437 int client_pid = pdbclient->
pid;
3438 if (client_pid == 0)
3442 db_msg(&msg,
MINFO,
"db_cleanup",
"Client \'%s\' on database \'%s\' pid %d does not exist and db_cleanup called by %s removed it", pdbclient->
name, pheader->
name, client_pid, who);
3456 db_msg(&msg,
MINFO,
"db_cleanup",
"Client \'%s\' on database \'%s\' pid %d timed out and db_cleanup called by %s removed it (idle %1.1lfs,TO %1.0lfs)",
3457 pdbclient->
name, pheader->
name, client_pid,
3474#ifdef LOCAL_ROUTINES
3504 if (!pdbclient->
pid)
3506 if ((client_name == NULL || client_name[0] == 0
3507 || strncmp(pdbclient->
name, client_name, strlen(client_name)) == 0)) {
3508 int client_pid = pdbclient->
pid;
3511 db_msg(&msg,
MINFO,
"db_cleanup2",
"Client \'%s\' on database \'%s\' pid %d does not exist and db_cleanup2 called by %s removed it",
3532 if ((interval > 0 && now - pdbclient->
last_activity > interval)) {
3533 db_msg(&msg,
MINFO,
"db_cleanup2",
"Client \'%s\' on database \'%s\' timed out and db_cleanup2 called by %s removed it (idle %1.1lfs,TO %1.0lfs)",
3536 (now - pdbclient->
last_activity) / 1000.0, interval / 1000.0);
3596 cm_msg(
MERROR,
"db_get_watchdog_info",
"invalid database handle");
3601 cm_msg(
MERROR,
"db_get_watchdog_info",
"invalid database handle");
3622 *timeout = *last = 0;
3641 cm_msg(
MERROR,
"db_check_client",
"invalid database handle");
3646 cm_msg(
MERROR,
"db_check_client",
"invalid database handle");
3668 int client_pid = atoi(pkey->
name);
3681 int size =
sizeof(
name);
3699 if (pclient->
pid == client_pid) {
3714 if (!found || dead) {
3722 db_msg(&msg,
MERROR,
"db_check_client",
"Cannot delete client info for client \'%s\', pid %d, db_delete_client_info() status %d",
name, client_pid,
status);
3724 db_msg(&msg,
MINFO,
"db_check_client",
"Deleted entry \'/System/Clients/%d\' for client \'%s\' because it is not connected to ODB", client_pid,
name);
3726 db_msg(&msg,
MINFO,
"db_check_client",
"Deleted entry \'/System/Clients/%d\' for client \'%s\' because process pid %d does not exists", client_pid,
name, client_pid);
3751#ifdef LOCAL_ROUTINES
3753 cm_msg(
MERROR,
"db_protect_database",
"invalid database handle %d",
hDB);
3766const char *
extract_key(
const char *key_list,
char *key_name,
int key_name_length)
3770 if (*key_list ==
'/')
3773 while (*key_list && *key_list !=
'/' && ++
i < key_name_length)
3774 *key_name++ = *key_list++;
3782 if (str1 == NULL && str2 != NULL)
3784 if (str1 != NULL && str2 == NULL)
3786 if (str1 == NULL && str2 == NULL)
3788 if (strlen(str1) != strlen(str2))
3792 if (toupper(*str1++) != toupper(*str2++))
3803 int len_str = strlen(
str);
3804 int len_suffix = strlen(suffix);
3807 if (len_suffix > len_str)
3826 if(pattern[1] == 0)
return true;
3842 }
else if(toupper(*
str) == toupper(*pattern)){
3855 *index1 = *index2 = 0;
3856 if (odbpath[strlen(odbpath) - 1] ==
']') {
3857 if (strchr(odbpath,
'[')) {
3858 if (*(strchr(odbpath,
'[') + 1) ==
'*')
3860 else if (strchr((strchr(odbpath,
'[') + 1),
'.') ||
3861 strchr((strchr(odbpath,
'[') + 1),
'-')) {
3862 *index1 = atoi(strchr(odbpath,
'[') + 1);
3863 pc = strchr(odbpath,
'[') + 1;
3864 while (*pc !=
'.' && *pc !=
'-')
3866 while (*pc ==
'.' || *pc ==
'-')
3870 *index1 = atoi(strchr(odbpath,
'[') + 1);
3874 *strchr(odbpath,
'[') = 0;
3893#ifdef LOCAL_ROUTINES
3898 cm_msg(
MERROR,
"db_create_key",
"invalid database handle");
3903 cm_msg(
MERROR,
"db_create_key",
"invalid database handle");
3926 KEY* newpkey = NULL;
3942#ifdef LOCAL_ROUTINES
3951 if (parentKey== NULL) {
3966 if (type <= 0 || type >=
TID_LAST) {
3971 const KEY* pdir = parentKey;
3974 db_msg(msg,
MERROR,
"db_create_key",
"cannot create \'%s\' in \'%s\' tid is %d, not a directory", key_name,
db_get_path_pkey(pheader, pdir).c_str(), pdir->
type);
3978 KEY* pcreated = NULL;
3980 const char* pkey_name = key_name;
4000 if (strcmp(
name,
"..") == 0) {
4007 if (strcmp(
name,
".") == 0)
4017 pprev = (
KEY*)pitem;
4050 db_msg(msg,
MERROR,
"db_create_key",
"online database full while creating \'%s\' in \'%s\'", key_name,
db_get_path_pkey(pheader, parentKey).c_str());
4070 if (pkeylist == NULL) {
4071 db_msg(msg,
MERROR,
"db_create_key",
"online database full while creating \'%s\' in \'%s'", key_name,
db_get_path_pkey(pheader, parentKey).c_str());
4094 db_msg(msg,
MERROR,
"db_create_key",
"online database full while creating \'%s\' in \'%s\'", key_name,
db_get_path_pkey(pheader, parentKey).c_str());
4116 db_msg(msg,
MERROR,
"db_create_key",
"online database full while creating \'%s\' in \'%s\'", key_name,
db_get_path_pkey(pheader, parentKey).c_str());
4142 if (!(*pkey_name ==
'/')) {
4144 db_msg(msg,
MERROR,
"db_create_key",
"object of type %d already exists at \"%s\" while creating \'%s\' of type %d in \'%s\'", pitem->
type,
db_get_path_pkey(pheader, pitem).c_str(), key_name,
type,
db_get_path_pkey(pheader, parentKey).c_str());
4150 *pnewkey = (
KEY*)pitem;
4156 db_msg(msg,
MERROR,
"db_create_key",
"path element \"%s\" in \"%s\" is not a subdirectory at \"%s\" while creating \'%s\' in \'%s\'",
name, key_name,
db_get_path_pkey(pheader, pitem).c_str(), key_name,
db_get_path_pkey(pheader, parentKey).c_str());
4162 }
while (*pkey_name ==
'/');
4164 assert(pcreated != NULL);
4167 *pnewkey = pcreated;
4191 if (destination == NULL) {
4192 cm_msg(
MERROR,
"db_create_link",
"link destination name is NULL");
4196 if (destination[0] !=
'/') {
4197 cm_msg(
MERROR,
"db_create_link",
"link destination name \'%s\' should start with \'/\', relative links are forbidden", destination);
4201 if (strlen(destination) < 1) {
4202 cm_msg(
MERROR,
"db_create_link",
"link destination name \'%s\' is too short", destination);
4206 if ((destination[0] ==
'/') && (destination[1] == 0)) {
4207 cm_msg(
MERROR,
"db_create_link",
"links to \"/\" are forbidden");
4214 cm_msg(
MERROR,
"db_create_link",
"Link destination \"%s\" does not exist", destination);
4230 cm_msg(
MERROR,
"db_create_link",
"Existing key \"%s\" is not a link", link_name);
4252#ifdef LOCAL_ROUTINES
4258#ifdef CHECK_OPEN_RECORD
4293 bool deny_delete =
false;
4333#ifdef CHECK_OPEN_RECORD
4377 ((
KEYLIST*)pkeylist)->num_keys--;
4433#ifdef LOCAL_ROUTINES
4466#ifdef LOCAL_ROUTINES
4504#ifdef LOCAL_ROUTINES
4536#ifdef LOCAL_ROUTINES
4549 db_msg(msg,
MERROR,
"db_find_key",
"Path \"%s\" tid %d is not a directory, looking for \"%s\"", path.c_str(), tid, key_name);
4555 if (key_name[0] == 0 || strcmp(key_name,
"/") == 0) {
4575 const char *pkey_name = key_name;
4577 assert(pkeylist!=NULL);
4585 if (strchr(
str,
'[') &&
str[strlen(
str) - 1] ==
']')
4586 *strchr(
str,
'[') = 0;
4589 if (strcmp(
str,
"..") == 0) {
4593 pkey = (
KEY *) ((
char *) pheader + pkeylist->
parent);
4597 if (strcmp(
str,
".") == 0)
4600 last_good_hkey =
hKey;
4617 db_msg(msg,
MERROR,
"db_find_key",
"hkey %d path \"%s\" invalid subdirectory entry hkey %d, looking for \"%s\"", last_good_hkey, path.c_str(),
hKey, key_name);
4623 db_msg(msg,
MERROR,
"db_find_key",
"hkey %d path \"%s\" invalid next_key %d, looking for \"%s\"",
hKey, path.c_str(), pkey->
next_key, key_name);
4650 mstrlcpy(
str, (
char *) pheader + pkey->
data,
sizeof(
str));
4651 if (
str[strlen(
str) - 1] ==
'/')
4652 str[strlen(
str) - 1] = 0;
4655 if (
str[strlen(
str) - 1] ==
']')
4660 mstrlcat(
str, pkey_name,
sizeof(
str));
4677 if (*pkey_name ==
'/') {
4698 }
while (*pkey_name ==
'/' && *(pkey_name + 1));
4756#ifdef LOCAL_ROUTINES
4785#ifndef DOXYGEN_SHOULD_SKIP_THIS
4818#ifdef LOCAL_ROUTINES
4873 char *pattern = NULL;
4874 char *subkeypath = NULL;
4875 char *parentkeypath = NULL;
4879 mstrlcpy(localpath, odbpath,
sizeof(localpath));
4880 parentkeypath = localpath;
4884 char *wildcard = strpbrk(localpath,
"*?");
4887 subkeypath = strchr(wildcard,
'/');
4893 parentkeypath = strrchr(localpath,
'/');
4894 if (parentkeypath) {
4897 pattern = parentkeypath+1;
4898 if((parentkeypath-1) == localpath){
4900 parentkeypath = NULL;
4902 parentkeypath = localpath;
4906 pattern = localpath;
4907 parentkeypath = NULL;
4916 if (parentkeypath) {
4928 hKeyVector.push_back(
hKey);
4934 for (
int i=0 ; ;
i++) {
4956 hKeyVector.push_back(hSubKey);
4964 if (hKeyVector.empty())
4993#ifdef LOCAL_ROUTINES
5000 cm_msg(
MERROR,
"db_get_parent",
"invalid database handle");
5005 cm_msg(
MERROR,
"db_get_parent",
"invalid database handle");
5017 pkey = (
const KEY *) ((
char *) pheader +
hKey);
5027 pkey = (
const KEY *) ((
char *) pheader + pkeylist->
parent);
5093#ifdef LOCAL_ROUTINES
5097 assert(pkey != NULL);
5110 while (subkey != NULL) {
5175#ifdef LOCAL_ROUTINES
5179 std::string path =
"";
5186 std::string xpath =
msprintf(
"(INVALID_KEY_TYPE_%d)", pkey->
type);;
5187 if (path.length() > 0) {
5195 std::string
str = path;
5197 if (pkey->
name[0] == 0) {
5198 path +=
"(EMPTY_NAME)";
5202 if (
str.length() > 0)
5211 return "(INVALID_PARENT_KEYLIST)/" + path;
5221 if (pkeylist->
parent == 0) {
5222 return "(NULL_PARENT)/" + path;
5226 return "(INVALID_PARENT)/" + path;
5229 pkey = (
const KEY *) ((
char *) pheader + pkeylist->
parent);
5234 return "(TRUNCATED)/" + path;
5255 return "(ZERO_HKEY)";
5260 return "(INVALID_HKEY)";
5263 const KEY* pkey = (
const KEY *) ((
char *) pheader +
hKey);
5297#ifdef LOCAL_ROUTINES
5310 mstrlcpy(path, xpath.c_str(), buf_size);
5344#ifdef LOCAL_ROUTINES
5351 return "(CANNOT LOCK ODB)";
5361 return "(no LOCAL_ROUTINES)";
5364#ifdef LOCAL_ROUTINES
5388 line += pclient->
name;
5395 line +=
" a deleted client";
5400 std::string *result = (std::string*)xresult;
5410 std::string *result = (std::string*)xresult;
5425 if (j < pclient->max_index)
5436 KEY *pkey = (
KEY *) ((
char *) pheader +
hKey);
5441 *result +=
" fixed\n";
5480#ifdef LOCAL_ROUTINES
5489 mstrlcpy(
str, result.c_str(), buf_size);
5529#ifdef LOCAL_ROUTINES
5533 if (num_values == 0)
5562#ifdef LOCAL_ROUTINES
5567 if (num_values == 0)
5580 if (data_size == 0) {
5581 db_msg(msg,
MERROR,
"db_set_value",
"zero data size not allowed");
5586 db_msg(msg,
MERROR,
"db_set_value",
"\"%s\" data_size %d does not match tid %d size %d times num_values %d", key_name, data_size,
type,
rpc_tid_size(
type), num_values);
5685#ifdef LOCAL_ROUTINES
5701 mstrlcpy(keyname, key_name,
sizeof(keyname));
5703 if (strchr(keyname,
'[') && strchr(keyname,
']')) {
5705 for (p = strchr(keyname,
'[') + 1; *p && *p !=
']'; p++)
5709 if (*p && *p ==
']') {
5710 idx = atoi(strchr(keyname,
'[') + 1);
5711 *strchr(keyname,
'[') = 0;
5771#ifdef LOCAL_ROUTINES
5794 memcpy(
data, (
char *) pheader + pkey->
data, *buf_size);
5795 db_msg(msg,
MERROR,
"db_get_data_locked",
"odb entry \"%s\" data truncated, size is %d (%d*%d), buffer size is only %d",
db_get_path_pkey(pheader, pkey).c_str(), pkey->
num_values * pkey->
item_size, pkey->
num_values, pkey->
item_size, *buf_size);
5857#ifdef LOCAL_ROUTINES
5864 cm_msg(
MERROR,
"db_enum_key",
"invalid database handle");
5869 cm_msg(
MERROR,
"db_enum_key",
"invalid database handle");
5925 cm_msg(
MERROR,
"db_enum_key",
"hkey %d path \"%s\" invalid first_key %d",
hKey, path.c_str(), xfirst_key);
5929 for (
i = 0;
i < idx;
i++) {
5933 cm_msg(
MERROR,
"db_enum_key",
"hkey %d path \"%s\" unexpected end of key list at index %d",
hKey, path.c_str(),
i);
5943 cm_msg(
MERROR,
"db_enum_key",
"hkey %d path \"%s\" invalid key list at index %d, next_key %d",
hKey, path.c_str(),
i, pkey->
next_key);
5950 const char*
str = (
char *) pheader + pkey->
data;
5953 if (strlen(
str) > 0 &&
str[strlen(
str) - 1] ==
']') {
5967 parent = pkeylist->
parent;
5986#ifndef DOXYGEN_SHOULD_SKIP_THIS
6020#ifdef LOCAL_ROUTINES
6028 cm_msg(
MERROR,
"db_enum_link",
"invalid database handle");
6033 cm_msg(
MERROR,
"db_enum_link",
"invalid database handle");
6052 pkey = (
KEY *) ((
char *) pheader +
hKey);
6058 pkeylist = (
KEYLIST *) ((
char *) pheader + pkey->
data);
6066 pkey = (
KEY *) ((
char *) pheader + pkeylist->
first_key);
6067 for (
i = 0;
i < idx;
i++) {
6069 pkey = (
KEY *) ((
char *) pheader + pkey->
next_key);
6107#ifdef LOCAL_ROUTINES
6115 cm_msg(
MERROR,
"db_enum_link",
"invalid database handle");
6120 cm_msg(
MERROR,
"db_enum_link",
"invalid database handle");
6139 pkey = (
KEY *) ((
char *) pheader +
hKey);
6147 pkey = (
KEY *) ((
char *) pheader + pkey->
next_key);
6168 pkey = (
KEY *) ((
char *) pheader + pkeylist->
parent);
6174 pkeylist = (
KEYLIST *) ((
char *) pheader + pkey->
data);
6182 pkey = (
KEY *) ((
char *) pheader + pkeylist->
first_key);
6200#ifdef LOCAL_ROUTINES
6205 sub_handles->clear();
6235 sub_handles->push_back(hlink);
6237 sub_keys->push_back(*plink);
6242 sub_handles->push_back(hsubkey);
6244 sub_keys->push_back(*psubkey);
6248 sub_handles->push_back(hsubkey);
6250 sub_keys->push_back(*psubkey);
6286 sub_handles->clear();
6291 for (
int i=0 ; ;
i++) {
6308 sub_handles->push_back(
hSubkey);
6310 sub_keys->push_back(subkey);
6317#ifdef LOCAL_ROUTINES
6320 sub_handles->clear();
6376 sub_handles->clear();
6391 for (
int i=0 ; ;
i++) {
6408 sub_handles->push_back(
hSubkey);
6410 sub_keys->push_back(subkey);
6417#ifdef LOCAL_ROUTINES
6420 sub_handles->clear();
6459#ifdef LOCAL_ROUTINES
6471 const KEY* pkey = (
const KEY *) ((
char *) pheader +
hKey);
6474 int pkey_type = pkey->
type;
6475 db_msg(msg,
MERROR,
"db_get_key",
"hkey %d invalid key type %d",
hKey, pkey_type);
6482 mstrlcpy(link_name, (
char *) pheader + pkey->
data,
sizeof(link_name));
6483 if (strlen(link_name) > 0 && link_name[strlen(link_name) - 1] ==
']') {
6484 if (strchr(link_name,
'[') == NULL)
6496 memcpy(
key, pkey,
sizeof(
KEY));
6543#ifdef LOCAL_ROUTINES
6549 cm_msg(
MERROR,
"db_get_key",
"invalid database handle");
6554 cm_msg(
MERROR,
"db_get_key",
"invalid database handle");
6596#ifdef LOCAL_ROUTINES
6601 cm_msg(
MERROR,
"db_get_link",
"invalid database handle");
6606 cm_msg(
MERROR,
"db_get_link",
"invalid database handle");
6625 memcpy(
key, pkey,
sizeof(
KEY));
6627 memset(
key, 0,
sizeof(
KEY));
6656#ifdef LOCAL_ROUTINES
6662 cm_msg(
MERROR,
"db_get_key",
"invalid database handle");
6667 cm_msg(
MERROR,
"db_get_key",
"invalid database handle");
6686 pkey = (
KEY *) ((
char *) pheader +
hKey);
6715#ifdef LOCAL_ROUTINES
6722 cm_msg(
MERROR,
"db_get_key_info",
"invalid database handle");
6727 cm_msg(
MERROR,
"db_get_key_info",
"invalid database handle");
6732 cm_msg(
MERROR,
"db_get_key_info",
"invalid key handle");
6746 pkey = (
KEY *) ((
char *) pheader +
hKey);
6748 if ((
INT) strlen(pkey->
name) + 1 > name_size) {
6750 memcpy(
name, pkey->
name, name_size - 1);
6751 name[name_size] = 0;
6756 if (strcmp(
name,
"root") == 0)
6764 pkeylist = (
KEYLIST *) ((
char *) pheader + pkey->
data);
6776#ifndef DOXYGEN_SHOULD_SKIP_THIS
6805#ifdef LOCAL_ROUTINES
6812 cm_msg(
MERROR,
"db_rename_key",
"invalid database handle");
6817 cm_msg(
MERROR,
"db_rename_key",
"invalid database handle");
6838 if (strlen(
name) < 1) {
6839 cm_msg(
MERROR,
"db_rename_key",
"key name is too short");
6843 if (strchr(
name,
'/')) {
6844 cm_msg(
MERROR,
"db_rename_key",
"key name may not contain \"/\"");
6858 pkey = (
KEY *) ((
char *) pheader +
hKey);
6861 int pkey_type = pkey->
type;
6863 cm_msg(
MERROR,
"db_rename_key",
"hkey %d invalid key type %d",
hKey, pkey_type);
6907#ifdef LOCAL_ROUTINES
6910 KEY *pkey, *pnext_key, *pkey_tmp;
6915 cm_msg(
MERROR,
"db_rename_key",
"invalid database handle");
6920 cm_msg(
MERROR,
"db_rename_key",
"invalid database handle");
6939 pkey = (
KEY *) ((
char *) pheader +
hKey);
6942 int pkey_type = pkey->
type;
6944 cm_msg(
MERROR,
"db_reorder_key",
"hkey %d invalid key type %d",
hKey, pkey_type);
6955#ifdef CHECK_OPEN_RECORD
6966 pkey = (
KEY *) ((
char *) pheader + pkeylist->
parent);
6971 pkey = (
KEY *) ((
char *) pheader +
hKey);
6977 if ((
KEY *) ((
char *) pheader + pkeylist->
first_key) == pkey) {
6983 pkey_tmp = (
KEY *) ((
char *) pheader + pkeylist->
first_key);
6984 while ((
KEY *) ((
char *) pheader + pkey_tmp->
next_key) != pkey) {
6986 pkey_tmp = (
KEY *) ((
char *) pheader + pkey_tmp->
next_key);
6993 pkey_tmp = (
KEY *) ((
char *) pheader + pkeylist->
first_key);
6994 if (idx < 0 || idx >= pkeylist->
num_keys - 1) {
7000 pkey_tmp = (
KEY *) ((
char *) pheader + pkey_tmp->
next_key);
7012 for (
i = 0;
i < idx - 1;
i++) {
7014 pkey_tmp = (
KEY *) ((
char *) pheader + pkey_tmp->
next_key);
7063#ifdef LOCAL_ROUTINES
7068 cm_msg(
MERROR,
"db_get_data",
"Invalid database handle");
7073 cm_msg(
MERROR,
"db_get_data",
"invalid database handle");
7106 std::string link_name = (
char *) pheader + pkey->
data;
7107 if (link_name.length() > 0 && link_name.back() ==
']') {
7108 size_t pos = link_name.rfind(
"[");
7109 if (pos == std::string::npos) {
7110 db_msg(&msg,
MERROR,
"db_get_data",
"missing \"[\" in symlink to array element \"%s\" in \"%s\"", link_name.c_str(),
db_get_path_pkey(pheader, pkey).c_str());
7116 int idx = atoi(link_name.c_str()+pos+1);
7117 link_name.resize(pos);
7121 if (link_name[0] !=
'/') {
7122 db_msg(&msg,
MERROR,
"db_get_data",
"symlink \"%s\" should start with \"/\" in \"%s\"", link_name.c_str(),
db_get_path_pkey(pheader, pkey).c_str());
7180#ifdef LOCAL_ROUTINES
7186 cm_msg(
MERROR,
"db_get_data",
"Invalid database handle");
7191 cm_msg(
MERROR,
"db_get_data",
"invalid database handle");
7210 pkey = (
KEY *) ((
char *) pheader +
hKey);
7219 int pkey_type = pkey->
type;
7221 cm_msg(
MERROR,
"db_get_data",
"hkey %d invalid key type %d",
hKey, pkey_type);
7226 int pkey_type = pkey->
type;
7228 mstrlcpy(pkey_name, pkey->
name,
sizeof(pkey_name));
7237 cm_msg(
MERROR,
"db_get_data",
"Key cannot contain data");
7242 if (pkey->
data == 0) {
7243 memset(
data, 0, *buf_size);
7252 memcpy(
data, (
char *) pheader + pkey->
data, *buf_size);
7255 cm_msg(
MERROR,
"db_get_data",
"data for key \"%s\" truncated from %d to %d bytes", path.c_str(), pkey_size, *buf_size);
7272#ifndef DOXYGEN_SHOULD_SKIP_THIS
7304#ifdef LOCAL_ROUTINES
7310 cm_msg(
MERROR,
"db_get_data",
"Invalid database handle");
7315 cm_msg(
MERROR,
"db_get_data",
"invalid database handle");
7334 pkey = (
KEY *) ((
char *) pheader +
hKey);
7343 int pkey_type = pkey->
type;
7345 cm_msg(
MERROR,
"db_get_data",
"hkey %d invalid key type %d",
hKey, pkey_type);
7350 int pkey_type = pkey->
type;
7352 mstrlcpy(pkey_name, pkey->
name,
sizeof(pkey_name));
7361 cm_msg(
MERROR,
"db_get_data",
"Key cannot contain data");
7366 if (pkey->
data == 0) {
7367 memset(
data, 0, *buf_size);
7376 memcpy(
data, (
char *) pheader + pkey->
data, *buf_size);
7379 cm_msg(
MERROR,
"db_get_data",
"data for key \"%s\" truncated from %d to %d bytes", path.c_str(), pkey_size, *buf_size);
7417#ifdef LOCAL_ROUTINES
7423 cm_msg(
MERROR,
"db_get_data",
"Invalid database handle");
7428 cm_msg(
MERROR,
"db_get_data",
"invalid database handle");
7447 pkey = (
KEY *) ((
char *) pheader +
hKey);
7456 int pkey_type = pkey->
type;
7458 cm_msg(
MERROR,
"db_get_data_index",
"hkey %d invalid key type %d",
hKey, pkey_type);
7463 int pkey_type = pkey->
type;
7465 mstrlcpy(pkey_name, pkey->
name,
sizeof(pkey_name));
7474 cm_msg(
MERROR,
"db_get_data_index",
"Key cannot contain data");
7479 if (pkey->
data == 0) {
7480 memset(
data, 0, *buf_size);
7489 memset(
data, 0, *buf_size);
7493 cm_msg(
MERROR,
"db_get_data_index",
"index (%d) exceeds array length (%d) for key \"%s\"", idx, pkey_num_values, path.c_str());
7504 cm_msg(
MERROR,
"db_get_data_index",
"data for key \"%s\" truncated from %d to %d bytes", path.c_str(), pkey_size, *buf_size);
7520#ifdef LOCAL_ROUTINES
7537 data_size = pkey->
item_size * num_values;
7544 if (pkey->
data == 0) {
7546 db_msg(msg,
MERROR, caller,
"Cannot reallocate \"%s\" with new size %d bytes, online database full",
db_get_path_pkey(pheader, pkey).c_str(), data_size);
7558 pkey->
item_size = data_size / num_values;
7564 mstrlcpy((
char *) pheader + pkey->
data, (
const char*)
data, data_size);
7567 memcpy((
char *) pheader + pkey->
data,
data, data_size);
7583 if (pkey->
data == 0) {
7586 db_msg(msg,
MERROR, caller,
"Cannot reallocate \"%s\" with new num_values %d and new size %d bytes, online database full",
db_get_path_pkey(pheader, pkey).c_str(), idx + 1, data_size * (idx + 1));
7639 if (num_values > 1) {
7641 if (data_size > 0 && num_values > 0)
7642 item_size = data_size/num_values;
7644 for (
int i=0;
i<num_values;
i++) {
7645 const char*
value = ((
const char*)
data) +
i * item_size;
7690 db_msg(msg,
MERROR,
"db_set_data_index",
"\"%s\" index %d is not a valid UTF-8 Unicode string",
db_get_path_pkey(pheader, pkey).c_str(), idx);
7739#ifdef LOCAL_ROUTINES
7746 cm_msg(
MERROR,
"db_set_data",
"invalid database handle");
7751 cm_msg(
MERROR,
"db_set_data",
"invalid database handle");
7760 if (num_values == 0)
7776 KEY* pkey = (
KEY *) ((
char *) pheader +
hKey);
7786 char link_name[256];
7787 mstrlcpy(link_name, (
char *) pheader + pkey->
data,
sizeof(link_name));
7788 if (strlen(link_name) > 0 && link_name[strlen(link_name) - 1] ==
']') {
7790 if (strchr(link_name,
'[') == NULL)
7792 link_idx = atoi(strchr(link_name,
'[') + 1);
7793 *strchr(link_name,
'[') = 0;
7842#ifdef LOCAL_ROUTINES
7848 char link_name[256];
7852 cm_msg(
MERROR,
"db_set_data1",
"invalid database handle");
7857 cm_msg(
MERROR,
"db_set_data1",
"invalid database handle");
7866 if (num_values == 0)
7880 pkey = (
KEY *) ((
char *) pheader +
hKey);
7890 mstrlcpy(link_name, (
char *) pheader + pkey->
data,
sizeof(link_name));
7891 if (strlen(link_name) > 0 && link_name[strlen(link_name) - 1] ==
']') {
7893 if (strchr(link_name,
'[') == NULL)
7895 link_idx = atoi(strchr(link_name,
'[') + 1);
7896 *strchr(link_name,
'[') = 0;
7949#ifdef LOCAL_ROUTINES
7952 cm_msg(
MERROR,
"db_set_data",
"invalid database handle");
7957 cm_msg(
MERROR,
"db_set_data",
"invalid database handle");
7966 if (num_values == 0)
7981 KEY* pkey = (
KEY *) ((
char *) pheader +
hKey);
8015#ifndef DOXYGEN_SHOULD_SKIP_THIS
8042#ifdef LOCAL_ROUTINES
8047 cm_msg(
MERROR,
"db_set_num_values",
"invalid database handle");
8052 cm_msg(
MERROR,
"db_set_num_values",
"invalid database handle");
8057 cm_msg(
MERROR,
"db_set_num_values",
"invalid key handle");
8061 if (num_values <= 0) {
8062 cm_msg(
MERROR,
"db_set_num_values",
"invalid num_values %d", num_values);
8066 if (num_values == 0)
8081 KEY* pkey = (
KEY *) ((
char *) pheader +
hKey);
8092 cm_msg(
MERROR,
"db_set_num_values",
"Key cannot contain data");
8104 cm_msg(
MERROR,
"db_set_num_values",
"Cannot resize array with item_size equal to zero");
8112 new_size = pkey->
item_size * num_values;
8116 if (pkey->
data == 0) {
8119 db_msg(&msg,
MERROR,
"db_set_num_values",
"Cannot resize \"%s\" with num_values %d and new size %d bytes, online database full",
db_get_path_pkey(pheader, pkey).c_str(), num_values, new_size);
8168#ifdef LOCAL_ROUTINES
8175 cm_msg(
MERROR,
"db_set_data_index",
"invalid database handle");
8180 cm_msg(
MERROR,
"db_set_data_index",
"invalid database handle");
8185 cm_msg(
MERROR,
"db_set_data_index",
"invalid key handle");
8201 KEY* pkey = (
KEY *) ((
char *) pheader +
hKey);
8211 char link_name[256];
8212 mstrlcpy(link_name, (
char *) pheader + pkey->
data,
sizeof(link_name));
8213 if (strlen(link_name) > 0 && link_name[strlen(link_name) - 1] ==
']') {
8215 if (strchr(link_name,
'[') == NULL)
8217 link_idx = atoi(strchr(link_name,
'[') + 1);
8218 *strchr(link_name,
'[') = 0;
8273#ifdef LOCAL_ROUTINES
8276 cm_msg(
MERROR,
"db_set_link_data_index",
"invalid database handle");
8281 cm_msg(
MERROR,
"db_set_link_data_index",
"invalid database handle");
8286 cm_msg(
MERROR,
"db_set_link_data_index",
"invalid key handle");
8302 KEY* pkey = (
KEY *) ((
char *) pheader +
hKey);
8336#ifndef DOXYGEN_SHOULD_SKIP_THIS
8370#ifdef LOCAL_ROUTINES
8373 cm_msg(
MERROR,
"db_set_data_index1",
"invalid database handle");
8378 cm_msg(
MERROR,
"db_set_data_index1",
"invalid database handle");
8383 cm_msg(
MERROR,
"db_set_data_index1",
"invalid key handle");
8399 KEY* pkey = (
KEY *) ((
char *) pheader +
hKey);
8465 if (num_values == 0)
8476 old_size = data_size;
8484#ifdef LOCAL_ROUTINES
8564#ifdef LOCAL_ROUTINES
8570 cm_msg(
MERROR,
"db_set_mode",
"invalid database handle");
8575 cm_msg(
MERROR,
"db_set_mode",
"invalid database handle");
8636 struct stat stat_buf;
8644 hfile = open(filename, O_RDONLY |
O_TEXT, 0644);
8646 cm_msg(
MERROR,
"db_load",
"file \"%s\" not found", filename);
8651 fstat(hfile, &stat_buf);
8652 size = stat_buf.st_size;
8653 buffer = (
char *) malloc(size + 1);
8655 if (buffer == NULL) {
8656 cm_msg(
MERROR,
"db_load",
"cannot allocate ODB load buffer");
8664 i =
read(hfile, buffer +
n, size -
n);
8672 if (strncmp(buffer,
"<?xml version=\"1.0\"", 19) == 0) {
8675 printf(
"Error in file \"%s\"\n", filename);
8676 }
else if( buffer[0] ==
'{'){
8677 if(strrchr(buffer,
'}')){
8734 std::string full_path = path;
8737 cm_msg(
MERROR,
"db_copy",
"ODB path too long at \"%s\"", path);
8755 data = (
char *) malloc(size);
8757 cm_msg(
MERROR,
"db_copy",
"cannot allocate data buffer");
8770 line +=
"[====#$@$#====]\n";
8773 if ((
INT) (line.length() + 1) > *buffer_size) {
8778 strcpy(buffer, line.c_str());
8779 buffer += line.length();
8780 *buffer_size -= line.length();
8788 strcpy(buffer,
data);
8789 buffer += strlen(
data);
8790 *buffer_size -= strlen(
data);
8792 line =
"\n====#$@$#====\n";
8814 if ((
INT) (line.length() + 1) > *buffer_size) {
8819 strcpy(buffer, line.c_str());
8820 buffer += line.length();
8821 *buffer_size -= line.length();
8828 if ((
INT) (line.length() + 1) > *buffer_size) {
8833 strcpy(buffer, line.c_str());
8834 buffer += line.length();
8835 *buffer_size -= line.length();
8848 if (strcmp(
key.
name,
"arr2") == 0)
8851 data = (
char *) malloc(size);
8853 cm_msg(
MERROR,
"db_copy",
"cannot allocate data buffer");
8862 if (*buffer_size < 2) {
8867 strcpy(buffer,
"\n");
8872 strcpy(
str, full_path.c_str());
8873 if (
str[0] &&
str[strlen(
str) - 1] !=
'/')
8884 buffer += strlen(buffer);
8906 line +=
"[====#$@$#====]\n";
8912 if ((
INT) (line.length() + 1) > *buffer_size) {
8917 strcpy(buffer, line.c_str());
8918 buffer += line.length();
8919 *buffer_size -= line.length();
8927 strcpy(buffer,
data);
8928 buffer += strlen(
data);
8929 *buffer_size -= strlen(
data);
8931 line =
"\n====#$@$#====\n";
8953 if ((
INT) (line.length() + 1) > *buffer_size) {
8958 strcpy(buffer, line.c_str());
8959 buffer += line.length();
8960 *buffer_size -= line.length();
8966 if ((
INT) (line.length() + 1) > *buffer_size) {
8971 strcpy(buffer, line.c_str());
8972 buffer += line.length();
8973 *buffer_size -= line.length();
8981 if (*buffer_size < 2)
8984 strcpy(buffer,
"\n");
9006 INT tid,
i,
j, n_data, string_length,
status, size;
9019 data = (
char *) malloc(data_size);
9021 cm_msg(
MERROR,
"db_paste",
"cannot allocate data buffer");
9032 line[
i] = *buffer++;
9036 cm_msg(
MERROR,
"db_paste",
"line too long: %s...", line);
9042 if (*buffer ==
'\n')
9046 if (line[0] ==
'[') {
9048 mstrlcpy(title, line + 1,
sizeof(title));
9049 if (strchr(title,
']'))
9050 *strchr(title,
']') = 0;
9051 if (title[0] && title[strlen(title) - 1] !=
'/')
9052 mstrlcat(title,
"/",
sizeof(title));
9055 if (strchr(line,
'=') && line[0] !=
';') {
9061 char* pline = strrchr(line,
'=') + 1;
9062 while (strstr(line,
": [") != NULL && strstr(line,
": [") < pline) {
9064 while (*pline !=
'=' && pline > line)
9068 while (*pline ==
' ')
9070 mstrlcpy(data_str, pline,
sizeof(data_str));
9073 *strrchr(line,
'=') = 0;
9074 while (strstr(line,
": [") && strchr(line,
'='))
9075 *strrchr(line,
'=') = 0;
9077 pline = &line[strlen(line) - 1];
9078 while (*pline ==
' ')
9082 if (title[0] !=
'.')
9083 mstrlcpy(key_name, title,
sizeof(key_name));
9085 mstrlcat(key_name, line,
sizeof(key_name));
9088 mstrlcpy(line, data_str,
sizeof(line));
9089 if (strchr(line,
' '))
9090 *strchr(line,
' ') = 0;
9093 if (strchr(line,
'[')) {
9094 n_data = atol(strchr(line,
'[') + 1);
9095 *strchr(line,
'[') = 0;
9098 for (tid = 0; tid <
TID_LAST; tid++)
9102 for (tid = 0; tid <
TID_LAST; tid++)
9110 cm_msg(
MERROR,
"db_paste",
"found unknown data type \"%s\" in ODB file", line);
9113 char* pc = data_str;
9114 while (*pc !=
' ' && *pc)
9116 while ((*pc ==
' ' || *pc ==
':') && *pc)
9120 assert(strlen(pc) <
sizeof(data_str));
9121 memmove(data_str, pc, strlen(pc)+1);
9128 for (
j = 0; *buffer !=
'\n' && *buffer;
j++)
9129 data_str[
j] = *buffer++;
9131 if (*buffer ==
'\n')
9135 for (
i = 0;
i < n_data;
i++) {
9137 char* pc = &data_str[strlen(data_str) - 1];
9138 while (*pc ==
'\n' || *pc ==
'\r')
9142 if (!string_length) {
9143 if (data_str[1] ==
'=')
9146 string_length = atoi(data_str + 1);
9149 cm_msg(
MERROR,
"db_paste",
"found string exceeding MAX_STRING_LENGTH, odb path \"%s\"", key_name);
9151 if (string_length == 0) {
9153 cm_msg(
MERROR,
"db_paste",
"found string length of zero, set to 32, odb path \"%s\"", key_name);
9157 if (string_length == -1) {
9159 if (strstr(buffer,
"\n====#$@$#====\n") != NULL) {
9160 string_length = (
POINTER_T) strstr(buffer,
"\n====#$@$#====\n") - (
POINTER_T) buffer + 1;
9162 if (string_length >= data_size) {
9163 data_size += string_length + 100;
9164 data = (
char *) realloc(
data, data_size);
9166 cm_msg(
MERROR,
"db_paste",
"cannot allocate data buffer");
9171 memset(
data, 0, data_size);
9172 strncpy(
data, buffer, string_length);
9173 data[string_length - 1] = 0;
9174 buffer = strstr(buffer,
"\n====#$@$#====\n") + strlen(
"\n====#$@$#====\n");
9176 cm_msg(
MERROR,
"db_paste",
"found multi-line string without termination sequence");
9178 char* pc = data_str + 2;
9179 while (*pc && *pc !=
' ')
9187 *(pc + string_length - 1) = 0;
9190 if (string_length * (
i + 1) >= data_size) {
9192 data = (
char *) realloc(
data, data_size);
9194 cm_msg(
MERROR,
"db_paste",
"cannot allocate data buffer");
9199 mstrlcpy(
data + string_length *
i, pc, string_length);
9202 char* pc = data_str;
9204 if (n_data > 1 && data_str[0] ==
'[') {
9205 index = atoi(data_str+1);
9206 pc = strchr(data_str,
']') + 1;
9207 while (*pc && *pc ==
' ')
9215 data = (
char *) realloc(
data, data_size);
9217 cm_msg(
MERROR,
"db_paste",
"cannot allocate data buffer");
9225 if (
i < n_data - 1) {
9232 for (
j = 0; *buffer !=
'\n' && *buffer;
j++)
9233 data_str[
j] = *buffer++;
9235 if (*buffer ==
'\n')
9240 if (data_str[0] == 0 || (strchr(data_str,
'=')
9241 && strchr(data_str,
':')))
9248 mstrlcpy(test_str, key_name,
sizeof(test_str));
9257 if (key_name[0] ==
'/') {
9297 if (strcmp(mxml_get_name(node),
"odb") == 0) {
9298 for (
int i = 0;
i < mxml_get_number_of_children(node);
i++) {
9303 }
else if (strcmp(mxml_get_name(node),
"dir") == 0) {
9304 const char*
name = mxml_get_attribute(node,
"name");
9307 cm_msg(
MERROR,
"db_paste_node",
"found key \"%s\" with no name in XML data", mxml_get_name(node));
9317 cm_msg(
MINFO,
"db_paste_node",
"cannot load key \"%s\": write protected",
name);
9334 for (
int i = 0;
i < mxml_get_number_of_children(node);
i++) {
9340 }
else if (strcmp(mxml_get_name(node),
"key") == 0 || strcmp(mxml_get_name(node),
"keyarray") == 0) {
9342 const char*
name = mxml_get_attribute(node,
"name");
9345 cm_msg(
MERROR,
"db_paste_node",
"found key \"%s\" with no name in XML data", mxml_get_name(node));
9350 if (strcmp(mxml_get_name(node),
"keyarray") == 0)
9351 num_values = atoi(mxml_get_attribute(node,
"num_values"));
9355 const char*
type = mxml_get_attribute(node,
"type");
9358 cm_msg(
MERROR,
"db_paste_node",
"found key \"%s\" with no type in XML data", mxml_get_name(node));
9364 cm_msg(
MERROR,
"db_paste_node",
"found unknown data type \"%s\" in XML data",
type);
9373 cm_msg(
MINFO,
"db_paste_node",
"cannot load key \"%s\": write protected",
name);
9407 size = atoi(mxml_get_attribute(node,
"size"));
9408 buf = (
char *)malloc(size);
9415 for (
int i = 0;
i < mxml_get_number_of_children(node);
i++) {
9416 PMXML_NODE child = mxml_subnode(node,
i);
9418 if (mxml_get_attribute(child,
"index"))
9419 idx = atoi(mxml_get_attribute(child,
"index"));
9423 if (mxml_get_value(child) == NULL) {
9426 cm_msg(
MINFO,
"db_paste_node",
"cannot load string or link \"%s\": write protected", mxml_get_attribute(node,
"name"));
9429 cm_msg(
MERROR,
"db_paste_node",
"cannot load string or link \"%s\": db_set_data_index() status %d", mxml_get_attribute(node,
"name"),
status);
9433 mstrlcpy(buf, mxml_get_value(child), size);
9436 cm_msg(
MINFO,
"db_paste_node",
"cannot load array element \"%s\": write protected", mxml_get_attribute(node,
"name"));
9439 cm_msg(
MERROR,
"db_paste_node",
"cannot load array element \"%s\": db_set_data_index() status %d", mxml_get_attribute(node,
"name"),
status);
9448 cm_msg(
MINFO,
"db_paste_node",
"cannot load array element \"%s\": write protected", mxml_get_attribute(node,
"name"));
9451 cm_msg(
MERROR,
"db_paste_node",
"cannot load array element \"%s\": db_set_data_index() status %d", mxml_get_attribute(node,
"name"),
status);
9459 size = atoi(mxml_get_attribute(node,
"size"));
9460 if (mxml_get_value(node) == NULL) {
9463 cm_msg(
MINFO,
"db_paste_node",
"cannot load string or link \"%s\": write protected", mxml_get_attribute(node,
"name"));
9466 cm_msg(
MERROR,
"db_paste_node",
"cannot load string or link \"%s\": db_set_data() status %d", mxml_get_attribute(node,
"name"),
status);
9470 mstrlcpy(buf, mxml_get_value(node), size);
9473 cm_msg(
MINFO,
"db_paste_node",
"cannot load value \"%s\": write protected", mxml_get_attribute(node,
"name"));
9476 cm_msg(
MERROR,
"db_paste_node",
"cannot load value \"%s\": db_set_data() status %d", mxml_get_attribute(node,
"name"),
status);
9485 cm_msg(
MINFO,
"db_paste_node",
"cannot load value \"%s\": write protected", mxml_get_attribute(node,
"name"));
9488 cm_msg(
MERROR,
"db_paste_node",
"cannot load value \"%s\": db_set_data() status %d", mxml_get_attribute(node,
"name"),
status);
9515 PMXML_NODE tree, node;
9521 tree = mxml_parse_buffer(buffer, error,
sizeof(error), NULL);
9527 node = mxml_find_node(tree,
"odb");
9529 puts(
"Cannot find element \"odb\" in XML data");
9535 mxml_free_tree(tree);
9556#ifdef LOCAL_ROUTINES
9560 MXML_WRITER *writer;
9563 writer = mxml_open_buffer();
9564 if (writer == NULL) {
9565 cm_msg(
MERROR,
"db_copy_xml",
"Cannot allocate buffer");
9573 mxml_start_element(writer,
"odb");
9574 mxml_write_attribute(writer,
"root", path.c_str());
9575 mxml_write_attribute(writer,
"xmlns:xsi",
"http://www.w3.org/2001/XMLSchema-instance");
9576 mxml_write_attribute(writer,
"xsi:noNamespaceSchemaLocation",
"http://midas.psi.ch/odb.xsd");
9579 mxml_end_element(writer);
9589 p = mxml_close_buffer(writer);
9590 len = strlen(p) + 1;
9591 if (len > *buffer_size) {
9597 mstrlcpy(buffer, p, len);
9607#ifndef DOXYGEN_SHOULD_SKIP_THIS
9619 if (*
str >=
'0' && *
str <=
'9')
9623 if (!(*
str >=
'a' && *
str <=
'z') && !(*
str >=
'A' && *
str <=
'Z') && !(*
str >=
'0' && *
str <=
'9'))
9625 *
str = (char) tolower(*
str);
9647 for (idx = 0;; idx++) {
9665 for (
i = 0;
i <= level;
i++) {
9666 wr =
write(hfile,
" ", 2);
9673 strcpy(line,
"char");
9676 strcpy(line,
"short");
9679 strcpy(line,
"float");
9682 strcpy(line,
"double");
9685 strcpy(line,
"unsigned char");
9688 strcpy(line,
"char");
9691 strcpy(line,
"char");
9698 mstrlcat(line,
" ",
sizeof(line));
9707 mstrlcpy(line + 10,
str,
sizeof(line) - 10);
9708 mstrlcat(line,
";\n",
sizeof(line));
9710 wr =
write(hfile, line, strlen(line));
9717 for (
i = 0;
i <= level;
i++) {
9718 wr =
write(hfile,
" ", 2);
9722 sprintf(line,
"struct {\n");
9723 wr =
write(hfile, line, strlen(line));
9727 for (
i = 0;
i <= level;
i++) {
9728 wr =
write(hfile,
" ", 2);
9735 sprintf(line,
"} %s;\n",
str);
9736 wr =
write(hfile, line, strlen(line));
9763#ifdef LOCAL_ROUTINES
9769 hfile = open(filename, O_WRONLY | O_CREAT | O_TRUNC |
O_TEXT, 0644);
9771 cm_msg(
MERROR,
"db_save",
"Cannot open file \"%s\"", filename);
9777 buffer_size = 10000;
9779 buffer = (
char *) malloc(buffer_size);
9780 if (buffer == NULL) {
9781 cm_msg(
MERROR,
"db_save",
"cannot allocate ODB dump buffer");
9788 n =
write(hfile, buffer, buffer_size - size);
9792 if (
n != buffer_size - size) {
9821 dst = (
char *) malloc(size);
9826 for (
i = 0;
i < (int) strlen(src);
i++) {
9829 mstrlcat(dst,
"<", size);
9832 mstrlcat(dst,
">", size);
9835 mstrlcat(dst,
"&", size);
9838 mstrlcat(dst,
""", size);
9841 mstrlcat(dst,
"'", size);
9844 if ((
int) strlen(dst) >= size) {
9848 p = dst + strlen(dst);
9854 mstrlcpy(src, dst, size);
9880 mxml_start_element(writer,
"dir");
9881 mxml_write_attribute(writer,
"name",
key.
name);
9882 mxml_write_attribute(writer,
"handle", std::to_string(
hKey).c_str());
9885 for (idx = 0;; idx++) {
9899 mxml_end_element(writer);
9905 mxml_start_element(writer,
"keyarray");
9907 mxml_start_element(writer,
"key");
9908 mxml_write_attribute(writer,
"name",
key.
name);
9910 mxml_write_attribute(writer,
"handle", std::to_string(
hKey).c_str());
9915 mxml_write_attribute(writer,
"size",
str);
9921 mxml_write_attribute(writer,
"num_values",
str);
9925 data = (
char *) malloc(size+1);
9927 cm_msg(
MERROR,
"db_save_xml_key",
"cannot allocate data buffer");
9936 mxml_write_value(writer,
data);
9941 cm_msg(
MERROR,
"db_save_xml_key",
"Long odb string probably truncated, odb path \"%s\", string length %d truncated to %d", path.c_str(), (
int)strlen(
data), (
int)
str.length());
9943 mxml_write_value(writer,
str.c_str());
9945 mxml_end_element(writer);
9951 mxml_start_element(writer,
"value");
9955 sprintf(
str,
"%d",
i);
9956 mxml_write_attribute(writer,
"index",
str);
9963 mxml_write_value(writer, p);
9968 cm_msg(
MERROR,
"db_save_xml_key",
"Long odb string array probably truncated, odb path \"%s\"[%d]", path.c_str(),
i);
9970 mxml_write_value(writer,
str.c_str());
9973 mxml_end_element(writer);
9976 mxml_end_element(writer);
10000#ifdef LOCAL_ROUTINES
10003 MXML_WRITER *writer;
10006 writer = mxml_open_file(filename);
10007 if (writer == NULL) {
10008 cm_msg(
MERROR,
"db_save_xml",
"Cannot open file \"%s\"", filename);
10015 mxml_start_element(writer,
"odb");
10016 mxml_write_attribute(writer,
"root", path.c_str());
10017 mxml_write_attribute(writer,
"filename", filename);
10018 mxml_write_attribute(writer,
"xmlns:xsi",
"http://www.w3.org/2001/XMLSchema-instance");
10020 std::string xsd_path;
10022 if (getenv(
"MIDASSYS"))
10023 xsd_path = getenv(
"MIDASSYS");
10028 xsd_path +=
"odb.xsd";
10029 mxml_write_attribute(writer,
"xsi:noNamespaceSchemaLocation", xsd_path.c_str());
10033 mxml_end_element(writer);
10034 mxml_close_file(writer);
10045void json_write(
char **buffer,
int* buffer_size,
int* buffer_end,
int level,
const char* s,
int quoted)
10047 int len, remain, xlevel;
10050 remain = *buffer_size - *buffer_end;
10051 assert(remain >= 0);
10055 while (10 + xlevel + 3*len > remain) {
10057 int new_buffer_size = 2*(*buffer_size);
10058 if (new_buffer_size < 4*1024)
10059 new_buffer_size = 4*1024;
10061 assert(new_buffer_size > *buffer_size);
10062 *buffer = (
char *)realloc(*buffer, new_buffer_size);
10064 *buffer_size = new_buffer_size;
10065 remain = *buffer_size - *buffer_end;
10066 assert(remain >= 0);
10071 for (
i=0;
i<xlevel;
i++)
10072 (*buffer)[(*buffer_end)++] =
' ';
10076 memcpy(*buffer + *buffer_end, s, len);
10077 *buffer_end += len;
10078 (*buffer)[*buffer_end] = 0;
10082 char *bufptr = *buffer;
10083 int bufend = *buffer_end;
10085 bufptr[bufend++] =
'"';
10090 bufptr[bufend++] =
'\\';
10091 bufptr[bufend++] =
'\"';
10095 bufptr[bufend++] =
'\\';
10096 bufptr[bufend++] =
'\\';
10101 bufptr[bufend++] =
'\\';
10102 bufptr[bufend++] =
'/';
10107 bufptr[bufend++] =
'\\';
10108 bufptr[bufend++] =
'b';
10112 bufptr[bufend++] =
'\\';
10113 bufptr[bufend++] =
'f';
10117 bufptr[bufend++] =
'\\';
10118 bufptr[bufend++] =
'n';
10122 bufptr[bufend++] =
'\\';
10123 bufptr[bufend++] =
'r';
10127 bufptr[bufend++] =
'\\';
10128 bufptr[bufend++] =
't';
10132 bufptr[bufend++] = *s++;
10136 bufptr[bufend++] =
'"';
10137 bufptr[bufend] = 0;
10139 *buffer_end = bufend;
10141 remain = *buffer_size - *buffer_end;
10142 assert(remain > 0);
10155 if (
comma !=
nullptr) {
10165 sprintf(
str,
"%u", *(
unsigned char*)p);
10169 sprintf(
str,
"%d", *(
char*)p);
10173 sprintf(
str,
"%c", *(
char*)p);
10177 sprintf(
str,
"\"0x%04x\"", *(
WORD*)p);
10181 sprintf(
str,
"%d", *(
short*)p);
10185 sprintf(
str,
"\"0x%08x\"", *(
DWORD*)p);
10189 sprintf(
str,
"%d", *(
int*)p);
10194 sprintf(
str,
"\"0x%016llx\"", *(
UINT64*)p);
10199 sprintf(
str,
"\"%lld\"", *(
INT64*)p);
10204 json_write(buffer, buffer_size, buffer_end, 0,
"true", 0);
10206 json_write(buffer, buffer_size, buffer_end, 0,
"false", 0);
10209 float flt = (*(
float*)p);
10211 json_write(buffer, buffer_size, buffer_end, 0,
"\"NaN\"", 0);
10212 else if (isinf(flt)) {
10214 json_write(buffer, buffer_size, buffer_end, 0,
"\"Infinity\"", 0);
10216 json_write(buffer, buffer_size, buffer_end, 0,
"\"-Infinity\"", 0);
10217 }
else if (flt == 0)
10218 json_write(buffer, buffer_size, buffer_end, 0,
"0", 0);
10219 else if (flt == (
int)flt) {
10220 sprintf(
str,
"%.0f", flt);
10224 sprintf(
str,
"%.7e", flt);
10231 double dbl = (*(
double*)p);
10233 json_write(buffer, buffer_size, buffer_end, 0,
"\"NaN\"", 0);
10234 else if (isinf(dbl)) {
10236 json_write(buffer, buffer_size, buffer_end, 0,
"\"Infinity\"", 0);
10238 json_write(buffer, buffer_size, buffer_end, 0,
"\"-Infinity\"", 0);
10239 }
else if (dbl == 0)
10240 json_write(buffer, buffer_size, buffer_end, 0,
"0", 0);
10241 else if (dbl == (
int)dbl) {
10242 sprintf(
str,
"%.0f", dbl);
10246 sprintf(
str,
"%.16e", dbl);
10253 json_write(buffer, buffer_size, buffer_end, 0,
"(TID_BITFIELD value)", 1);
10257 json_write(buffer, buffer_size, buffer_end, 0, p, 1);
10260 json_write(buffer, buffer_size, buffer_end, 0,
"(TID_ARRAY value)", 1);
10263 json_write(buffer, buffer_size, buffer_end, 0,
"(TID_STRUCT value)", 1);
10266 json_write(buffer, buffer_size, buffer_end, 0,
"{ }", 0);
10270 json_write(buffer, buffer_size, buffer_end, 0, p, 1);
10273 json_write(buffer, buffer_size, buffer_end, 0,
"(TID_UNKNOWN value)", 1);
10281 json_write(buffer, buffer_size, buffer_end, 0,
"{ ", 0);
10287 json_write(buffer, buffer_size, buffer_end, 0,
", ", 0);
10288 json_write(buffer, buffer_size, buffer_end, 0,
"link", 1);
10289 json_write(buffer, buffer_size, buffer_end, 0,
": ", 0);
10290 json_write(buffer, buffer_size, buffer_end, 0, link_path, 1);
10294 json_write(buffer, buffer_size, buffer_end, 0,
", ", 0);
10301 json_write(buffer, buffer_size, buffer_end, 0,
", ", 0);
10308 json_write(buffer, buffer_size, buffer_end, 0,
", ", 0);
10314 json_write(buffer, buffer_size, buffer_end, 0,
", ", 0);
10319 json_write(buffer, buffer_size, buffer_end, 0,
", ", 0);
10324 json_write(buffer, buffer_size, buffer_end, 0,
" ", 0);
10326 json_write(buffer, buffer_size, buffer_end, 0,
"}", 0);
10336 int omit_top_level_braces = 0;
10342 omit_top_level_braces = 1;
10353 size =
sizeof(link_path);
10359 if (follow_links) {
10376 int do_close_curly_bracket = 0;
10378 if (level == 0 && !omit_top_level_braces) {
10379 json_write(buffer, buffer_size, buffer_end, 0,
"{\n", 0);
10380 do_close_curly_bracket = 1;
10382 else if (level > 0) {
10383 json_write(buffer, buffer_size, buffer_end, level, link_key.
name, 1);
10384 json_write(buffer, buffer_size, buffer_end, 0,
" : {\n", 0);
10385 do_close_curly_bracket = 1;
10391 json_write(buffer, buffer_size, buffer_end, 0,
"/error", 1);
10392 json_write(buffer, buffer_size, buffer_end, 0,
" : ", 0);
10393 json_write(buffer, buffer_size, buffer_end, 0,
"max nesting level exceed", 1);
10395 cm_msg(
MERROR,
"db_save_json_key",
"max nesting level exceeded at \"%s\", check for symlink loops in this subtree", path.c_str());
10407 json_write(buffer, buffer_size, buffer_end, 0,
",\n", 0);
10417 if (do_close_curly_bracket) {
10419 json_write(buffer, buffer_size, buffer_end, 0,
"\n", 0);
10420 json_write(buffer, buffer_size, buffer_end, level,
"}", 0);
10425 if (save_keys && level == 0) {
10426 json_write(buffer, buffer_size, buffer_end, 0,
"{\n", 0);
10431 if (save_keys == 1) {
10433 sprintf(
str,
"%s/key", link_key.
name);
10435 json_write(buffer, buffer_size, buffer_end, level,
str, 1);
10436 json_write(buffer, buffer_size, buffer_end, 0,
" : { ", 0);
10442 json_write(buffer, buffer_size, buffer_end, 0,
", ", 0);
10443 json_write(buffer, buffer_size, buffer_end, 0,
"link", 1);
10444 json_write(buffer, buffer_size, buffer_end, 0,
": ", 0);
10445 json_write(buffer, buffer_size, buffer_end, 0, link_path, 1);
10449 json_write(buffer, buffer_size, buffer_end, 0,
", ", 0);
10456 json_write(buffer, buffer_size, buffer_end, 0,
", ", 0);
10463 json_write(buffer, buffer_size, buffer_end, 0,
", ", 0);
10469 json_write(buffer, buffer_size, buffer_end, 0,
", ", 0);
10474 json_write(buffer, buffer_size, buffer_end, 0,
", ", 0);
10479 json_write(buffer, buffer_size, buffer_end, 0,
" ", 0);
10481 json_write(buffer, buffer_size, buffer_end, 0,
"}", 0);
10483 json_write(buffer, buffer_size, buffer_end, 0,
",\n", 0);
10486 if (save_keys == 2) {
10488 sprintf(
str,
"%s/last_written", link_key.
name);
10490 json_write(buffer, buffer_size, buffer_end, level,
str, 1);
10495 json_write(buffer, buffer_size, buffer_end, 0,
",\n", 0);
10499 json_write(buffer, buffer_size, buffer_end, level, link_key.
name, 1);
10500 json_write(buffer, buffer_size, buffer_end, 0,
" : ", 0);
10504 json_write(buffer, buffer_size, buffer_end, 0,
"[ ", 0);
10508 data = (
char *) malloc(size);
10509 if (
data == NULL) {
10510 cm_msg(
MERROR,
"db_save_json_key",
"cannot allocate data buffer for %d bytes", size);
10529 json_write(buffer, buffer_size, buffer_end, 0,
", ", 0);
10533 sprintf(
str,
"%u", *(
unsigned char*)p);
10537 sprintf(
str,
"%d", *(
char*)p);
10541 sprintf(
str,
"%c", *(
char*)p);
10545 sprintf(
str,
"\"0x%04x\"", *(
WORD*)p);
10549 sprintf(
str,
"%d", *(
short*)p);
10553 sprintf(
str,
"\"0x%08x\"", *(
DWORD*)p);
10557 sprintf(
str,
"%d", *(
int*)p);
10561 sprintf(
str,
"\"0x%08llx\"", *(
UINT64*)p);
10570 json_write(buffer, buffer_size, buffer_end, 0,
"true", 0);
10572 json_write(buffer, buffer_size, buffer_end, 0,
"false", 0);
10575 float flt = (*(
float*)p);
10577 json_write(buffer, buffer_size, buffer_end, 0,
"\"NaN\"", 0);
10578 else if (isinf(flt)) {
10580 json_write(buffer, buffer_size, buffer_end, 0,
"\"Infinity\"", 0);
10582 json_write(buffer, buffer_size, buffer_end, 0,
"\"-Infinity\"", 0);
10583 }
else if (flt == 0)
10584 json_write(buffer, buffer_size, buffer_end, 0,
"0", 0);
10585 else if (flt == (
int)flt) {
10586 sprintf(
str,
"%.0f", flt);
10589 sprintf(
str,
"%.7e", flt);
10595 double dbl = (*(
double*)p);
10597 json_write(buffer, buffer_size, buffer_end, 0,
"\"NaN\"", 0);
10598 else if (isinf(dbl)) {
10600 json_write(buffer, buffer_size, buffer_end, 0,
"\"Infinity\"", 0);
10602 json_write(buffer, buffer_size, buffer_end, 0,
"\"-Infinity\"", 0);
10603 }
else if (dbl == 0)
10604 json_write(buffer, buffer_size, buffer_end, 0,
"0", 0);
10605 else if (dbl == (
int)dbl) {
10606 sprintf(
str,
"%.0f", dbl);
10609 sprintf(
str,
"%.16e", dbl);
10615 json_write(buffer, buffer_size, buffer_end, 0,
"(TID_BITFIELD value)", 1);
10619 json_write(buffer, buffer_size, buffer_end, 0, p, 1);
10622 json_write(buffer, buffer_size, buffer_end, 0,
"(TID_ARRAY value)", 1);
10625 json_write(buffer, buffer_size, buffer_end, 0,
"(TID_STRUCT value)", 1);
10628 json_write(buffer, buffer_size, buffer_end, 0,
"{ }", 0);
10632 json_write(buffer, buffer_size, buffer_end, 0, p, 1);
10635 json_write(buffer, buffer_size, buffer_end, 0,
"(TID_UNKNOWN value)", 1);
10641 json_write(buffer, buffer_size, buffer_end, 0,
" ]", 0);
10643 json_write(buffer, buffer_size, buffer_end, 0,
"", 0);
10649 if (save_keys && level == 0) {
10650 json_write(buffer, buffer_size, buffer_end, 0,
"\n}", 0);
10686 json_write(buffer, buffer_size, buffer_end, 0,
"0", 0);
10689 json_write(buffer, buffer_size, buffer_end, 0,
"0", 0);
10692 json_write(buffer, buffer_size, buffer_end, 0,
" ", 1);
10695 json_write(buffer, buffer_size, buffer_end, 0,
"0x0000", 1);
10698 json_write(buffer, buffer_size, buffer_end, 0,
"0", 0);
10701 json_write(buffer, buffer_size, buffer_end, 0,
"0x00000000", 1);
10704 json_write(buffer, buffer_size, buffer_end, 0,
"0", 0);
10707 json_write(buffer, buffer_size, buffer_end, 0,
"0x0000000000000000", 1);
10710 json_write(buffer, buffer_size, buffer_end, 0,
"0", 1);
10713 json_write(buffer, buffer_size, buffer_end, 0,
"false", 0);
10716 json_write(buffer, buffer_size, buffer_end, 0,
"0", 0);
10720 json_write(buffer, buffer_size, buffer_end, 0,
"0", 0);
10724 json_write(buffer, buffer_size, buffer_end, 0,
"(TID_BITFIELD value)", 1);
10727 json_write(buffer, buffer_size, buffer_end, 0,
"", 1);
10730 json_write(buffer, buffer_size, buffer_end, 0,
"(TID_ARRAY value)", 1);
10733 json_write(buffer, buffer_size, buffer_end, 0,
"(TID_STRUCT value)", 1);
10736 json_write(buffer, buffer_size, buffer_end, 0,
"{ }", 0);
10739 json_write(buffer, buffer_size, buffer_end, 0,
"", 1);
10742 json_write(buffer, buffer_size, buffer_end, 0,
"(TID_UNKNOWN value)", 1);
10749 json_write(buffer, buffer_size, buffer_end, 0,
"[ ", 0);
10758 data = (
char *) malloc(asize);
10759 if (
data == NULL) {
10760 cm_msg(
MERROR,
"db_save_json_key_data",
"cannot allocate data buffer for %d bytes", asize);
10776 json_write(buffer, buffer_size, buffer_end, 0,
", ", 0);
10782 json_write(buffer, buffer_size, buffer_end, 0,
" ]", 0);
10814 char*
data = (
char*)malloc(size + 1);
10815 assert(
data != NULL);
10838 char* link_path = NULL;
10840 HNDLE hLinkTarget = hLink;
10843 int size =
sizeof(link_buf);
10850 if ((size > 0) && (strlen(link_buf) > 0)) {
10851 link_path = link_buf;
10858 hLinkTarget = hLink;
10879 json_write(buffer, buffer_size, buffer_end, 0,
",\n", 0);
10881 json_write(buffer, buffer_size, buffer_end, 0,
"\n", 0);
10886 mstrlcpy(link_name, link.
name,
sizeof(link_name));
10889 for (
int i=0; (
i<(int)
sizeof(link.
name)) && link.
name[
i];
i++)
10890 link_name[
i] = tolower(link.
name[
i]);
10895 mstrlcpy(buf, link_name,
sizeof(buf));
10896 mstrlcat(buf,
"/name",
sizeof(buf));
10897 json_write(buffer, buffer_size, buffer_end, level, buf, 1);
10898 json_write(buffer, buffer_size, buffer_end, 0,
" : " , 0);
10900 json_write(buffer, buffer_size, buffer_end, 0,
",\n", 0);
10905 mstrlcpy(buf, link_name,
sizeof(buf));
10906 mstrlcat(buf,
"/key",
sizeof(buf));
10907 json_write(buffer, buffer_size, buffer_end, level, buf, 1);
10908 json_write(buffer, buffer_size, buffer_end, 0,
" : " , 0);
10909 json_write_key(
hDB, hLink, &link_target, link_path, buffer, buffer_size, buffer_end);
10910 json_write(buffer, buffer_size, buffer_end, 0,
",\n", 0);
10913 mstrlcpy(buf, link_name,
sizeof(buf));
10914 mstrlcat(buf,
"/last_written",
sizeof(buf));
10915 json_write(buffer, buffer_size, buffer_end, level, buf, 1);
10916 json_write(buffer, buffer_size, buffer_end, 0,
" : " , 0);
10918 json_write(buffer, buffer_size, buffer_end, 0, buf, 0);
10919 json_write(buffer, buffer_size, buffer_end, 0,
",\n", 0);
10922 json_write(buffer, buffer_size, buffer_end, level, link_name, 1);
10923 json_write(buffer, buffer_size, buffer_end, 0,
" : " , 0);
10926 json_write(buffer, buffer_size, buffer_end, 0,
"{ }" , 0);
10943 for (
int i=0; ;
i++) {
10956 bool need_comma = (
i!=0);
10977 json_write(buffer, buffer_size, buffer_end, 0,
"{", 0);
10983 json_write(buffer, buffer_size, buffer_end, 0,
"\n", 0);
10984 json_write(buffer, buffer_size, buffer_end, level,
"}", 0);
10986 }
else if (must_be_subdir) {
10987 json_write(buffer, buffer_size, buffer_end, 0,
"{", 0);
10991 json_write(buffer, buffer_size, buffer_end, 0,
"\n", 0);
10992 json_write(buffer, buffer_size, buffer_end, level,
"}", 0);
11006 bool unlock =
false;
11031 if (omit_last_written)
11033 if (omit_old_timestamp)
11035 if (!preserve_case)
11038 bool unlock =
false;
11060 bool unlock =
false;
11093 json_write(buffer, buffer_size, buffer_end, 0,
"\n", 0);
11114 FILE *
fp = fopen(filename,
"w");
11116 cm_msg(
MERROR,
"db_save_json",
"Cannot open file \"%s\", fopen() errno %d (%s)", filename, errno, strerror(errno));
11120 bool unlock =
false;
11133 bool emptySubdir =
false;
11137 emptySubdir =
true;
11139 char* buffer = NULL;
11140 int buffer_size = 0;
11141 int buffer_end = 0;
11143 json_write(&buffer, &buffer_size, &buffer_end, 0,
"{\n", 0);
11145 json_write(&buffer, &buffer_size, &buffer_end, 1,
"/MIDAS version", 1);
11146 json_write(&buffer, &buffer_size, &buffer_end, 0,
" : ", 0);
11148 json_write(&buffer, &buffer_size, &buffer_end, 0,
",\n", 0);
11150 json_write(&buffer, &buffer_size, &buffer_end, 1,
"/MIDAS git revision", 1);
11151 json_write(&buffer, &buffer_size, &buffer_end, 0,
" : ", 0);
11152 json_write(&buffer, &buffer_size, &buffer_end, 0, GIT_REVISION, 1);
11153 json_write(&buffer, &buffer_size, &buffer_end, 0,
",\n", 0);
11155 json_write(&buffer, &buffer_size, &buffer_end, 1,
"/filename", 1);
11156 json_write(&buffer, &buffer_size, &buffer_end, 0,
" : ", 0);
11157 json_write(&buffer, &buffer_size, &buffer_end, 0, filename, 1);
11158 json_write(&buffer, &buffer_size, &buffer_end, 0,
",\n", 0);
11160 json_write(&buffer, &buffer_size, &buffer_end, 1,
"/ODB path", 1);
11161 json_write(&buffer, &buffer_size, &buffer_end, 0,
" : ", 0);
11162 json_write(&buffer, &buffer_size, &buffer_end, 0, path.c_str(), 1);
11165 json_write(&buffer, &buffer_size, &buffer_end, 0,
"", 0);
11167 json_write(&buffer, &buffer_size, &buffer_end, 0,
",\n", 0);
11172 json_write(&buffer, &buffer_size, &buffer_end, 0,
"\n}\n", 0);
11180 size_t wr = fwrite(buffer, 1, buffer_end,
fp);
11181 if (wr != (
size_t)buffer_end) {
11182 cm_msg(
MERROR,
"db_save_json",
"Cannot write to file \"%s\", fwrite() errno %d (%s)", filename, errno, strerror(errno));
11212 char str[100], line[10+100];
11217 fh = open(
file_name, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0644);
11230 sprintf(line,
"typedef struct {\n");
11232 size = strlen(line);
11233 wr =
write(fh, line, size);
11235 cm_msg(
MERROR,
"db_save_struct",
"file \"%s\" write error: write(%d) returned %d, errno %d (%s)",
file_name, size, wr, errno, strerror(errno));
11242 if (struct_name && struct_name[0])
11243 mstrlcpy(
str, struct_name,
sizeof(
str));
11248 for (
i = 0;
i < (int) strlen(
str);
i++)
11251 sprintf(line,
"} %s;\n\n",
str);
11253 size = strlen(line);
11254 wr =
write(fh, line, size);
11256 cm_msg(
MERROR,
"db_save_struct",
"file \"%s\" write error: write(%d) returned %d, errno %d (%s)",
file_name, size, wr, errno, strerror(errno));
11267#ifndef DOXYGEN_SHOULD_SKIP_THIS
11295 char str[256], line[50+256];
11297 char *buffer = NULL, *pc;
11302 fh = open(
file_name, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0644);
11315 if (string_name && string_name[0])
11316 strcpy(
str, string_name);
11321 for (
i = 0;
i < (int) strlen(
str);
i++)
11324 sprintf(line,
"#define %s(_name) const char *_name[] = {\\\n",
str);
11325 size = strlen(line);
11326 wr =
write(fh, line, size);
11328 cm_msg(
MERROR,
"db_save",
"file \"%s\" write error: write(%d) returned %d, errno %d (%s)",
file_name, size, wr, errno, strerror(errno));
11335 buffer_size = 10000;
11337 buffer = (
char *) malloc(buffer_size);
11338 if (buffer == NULL) {
11339 cm_msg(
MERROR,
"db_save",
"cannot allocate ODB dump buffer");
11343 size = buffer_size;
11360 while (*pc !=
'\n' && *pc != 0) {
11361 if (*pc ==
'\"' || *pc ==
'\'')
11365 strcpy(&line[
i],
"\",\\\n");
11367 size = strlen(line);
11368 wr =
write(fh, line, size);
11370 cm_msg(
MERROR,
"db_save",
"file \"%s\" write error: write(%d) returned %d, errno %d (%s)",
file_name, size, wr, errno, strerror(errno));
11383 sprintf(line,
"NULL }\n\n");
11384 size = strlen(line);
11385 wr =
write(fh, line, size);
11387 cm_msg(
MERROR,
"db_save",
"file \"%s\" write error: write(%d) returned %d, errno %d (%s)",
file_name, size, wr, errno, strerror(errno));
11428 if (data_size == 0)
11429 sprintf(
string,
"<NULL>");
11433 sprintf(
string,
"%d", *(((
BYTE *)
data) + idx));
11436 sprintf(
string,
"%d", *(((
char *)
data) + idx));
11439 sprintf(
string,
"%c", *(((
char *)
data) + idx));
11442 sprintf(
string,
"%u", *(((
WORD *)
data) + idx));
11445 sprintf(
string,
"%d", *(((
short *)
data) + idx));
11448 sprintf(
string,
"%u", *(((
DWORD *)
data) + idx));
11451 sprintf(
string,
"%d", *(((
INT *)
data) + idx));
11454 sprintf(
string,
"%llu", *(((
UINT64 *)
data) + idx));
11457 sprintf(
string,
"%lld", *(((
INT64 *)
data) + idx));
11460 sprintf(
string,
"%c", *(((
BOOL *)
data) + idx) ?
'y' :
'n');
11464 sprintf(
string,
"NAN");
11466 sprintf(
string,
"%.7g", *(((
float *)
data) + idx));
11470 sprintf(
string,
"NAN");
11472 sprintf(
string,
"%.16lg", *(((
double *)
data) + idx));
11475 sprintf(
string,
"%u", *(((
DWORD *)
data) + idx));
11482 sprintf(
string,
"<unknown>");
11504 if (data_size == 0)
11505 sprintf(
string,
"<NULL>");
11509 sprintf(
string, format, *(((
BYTE *)
data) + idx));
11512 sprintf(
string, format, *(((
char *)
data) + idx));
11515 sprintf(
string, format, *(((
char *)
data) + idx));
11518 sprintf(
string, format, *(((
WORD *)
data) + idx));
11521 sprintf(
string, format, *(((
short *)
data) + idx));
11524 sprintf(
string, format, *(((
DWORD *)
data) + idx));
11527 sprintf(
string, format, *(((
INT *)
data) + idx));
11530 sprintf(
string, format, *(((
UINT64 *)
data) + idx));
11533 sprintf(
string, format, *(((
INT64 *)
data) + idx));
11536 sprintf(
string, format, *(((
BOOL *)
data) + idx) ?
'y' :
'n');
11540 sprintf(
string,
"NAN");
11542 sprintf(
string, format, *(((
float *)
data) + idx));
11546 sprintf(
string,
"NAN");
11548 sprintf(
string, format, *(((
double *)
data) + idx));
11551 sprintf(
string, format, *(((
DWORD *)
data) + idx));
11558 sprintf(
string,
"<unknown>");
11588 if (data_size == 0)
11589 sprintf(
string,
"<NULL>");
11593 sprintf(
string,
"0x%X", *(((
BYTE *)
data) + idx));
11596 sprintf(
string,
"0x%X", *(((
char *)
data) + idx));
11599 sprintf(
string,
"%c", *(((
char *)
data) + idx));
11602 sprintf(
string,
"0x%X", *(((
WORD *)
data) + idx));
11605 sprintf(
string,
"0x%hX", *(((
short *)
data) + idx));
11608 sprintf(
string,
"0x%X", *(((
DWORD *)
data) + idx));
11611 sprintf(
string,
"0x%X", *(((
INT *)
data) + idx));
11614 sprintf(
string,
"0x%llX", *(((
UINT64 *)
data) + idx));
11617 sprintf(
string,
"0x%llX", *(((
INT64 *)
data) + idx));
11620 sprintf(
string,
"%c", *(((
BOOL *)
data) + idx) ?
'y' :
'n');
11624 sprintf(
string,
"NAN");
11626 sprintf(
string,
"%.7g", *(((
float *)
data) + idx));
11630 sprintf(
string,
"NAN");
11632 sprintf(
string,
"%.16lg", *(((
double *)
data) + idx));
11635 sprintf(
string,
"0x%X", *(((
DWORD *)
data) + idx));
11639 sprintf(
string,
"%s", ((
char *)
data) + data_size * idx);
11642 sprintf(
string,
"<unknown>");
11672 if (data_size == 0) {
11678 sprintf(buf,
"%d", *(((
BYTE *)
data) + idx));
11681 sprintf(buf,
"%d", *(((
char *)
data) + idx));
11684 sprintf(buf,
"%c", *(((
char *)
data) + idx));
11687 sprintf(buf,
"%u", *(((
WORD *)
data) + idx));
11690 sprintf(buf,
"%d", *(((
short *)
data) + idx));
11693 sprintf(buf,
"%u", *(((
DWORD *)
data) + idx));
11696 sprintf(buf,
"%d", *(((
INT *)
data) + idx));
11699 sprintf(buf,
"%llu", *(((
UINT64 *)
data) + idx));
11702 sprintf(buf,
"%lld", *(((
INT64 *)
data) + idx));
11705 sprintf(buf,
"%c", *(((
BOOL *)
data) + idx) ?
'y' :
'n');
11711 sprintf(buf,
"%.7g", *(((
float *)
data) + idx));
11718 sprintf(buf,
"%.16lg", *(((
double *)
data) + idx));
11722 sprintf(buf,
"%u", *(((
DWORD *)
data) + idx));
11726 return (((
char *)
data) + data_size * idx);
11728 return "<unknown>";
11748 if (data_size == 0) {
11754 sprintf(buf, format, *(((
BYTE *)
data) + idx));
11757 sprintf(buf, format, *(((
char *)
data) + idx));
11760 sprintf(buf, format, *(((
char *)
data) + idx));
11763 sprintf(buf, format, *(((
WORD *)
data) + idx));
11766 sprintf(buf, format, *(((
short *)
data) + idx));
11769 sprintf(buf, format, *(((
DWORD *)
data) + idx));
11772 sprintf(buf, format, *(((
INT *)
data) + idx));
11775 sprintf(buf, format, *(((
UINT64 *)
data) + idx));
11778 sprintf(buf, format, *(((
INT64 *)
data) + idx));
11781 sprintf(buf, format, *(((
BOOL *)
data) + idx) ?
'y' :
'n');
11787 sprintf(buf, format, *(((
float *)
data) + idx));
11794 sprintf(buf, format, *(((
double *)
data) + idx));
11798 sprintf(buf, format, *(((
DWORD *)
data) + idx));
11802 return (((
char *)
data) + data_size * idx);
11804 return "<unknown>";
11810#ifndef DOXYGEN_SHOULD_SKIP_THIS
11835 if (data_size == 0) {
11841 sprintf(buf,
"0x%X", *(((
BYTE *)
data) + idx));
11844 sprintf(buf,
"0x%X", *(((
char *)
data) + idx));
11847 sprintf(buf,
"%c", *(((
char *)
data) + idx));
11850 sprintf(buf,
"0x%X", *(((
WORD *)
data) + idx));
11853 sprintf(buf,
"0x%hX", *(((
short *)
data) + idx));
11856 sprintf(buf,
"0x%X", *(((
DWORD *)
data) + idx));
11859 sprintf(buf,
"0x%X", *(((
INT *)
data) + idx));
11862 sprintf(buf,
"0x%llX", *(((
UINT64 *)
data) + idx));
11865 sprintf(buf,
"0x%llX", *(((
INT64 *)
data) + idx));
11868 sprintf(buf,
"%c", *(((
BOOL *)
data) + idx) ?
'y' :
'n');
11874 sprintf(buf,
"%.7g", *(((
float *)
data) + idx));
11881 sprintf(buf,
"%.16lg", *(((
double *)
data) + idx));
11885 sprintf(buf,
"0x%X", *(((
DWORD *)
data) + idx));
11889 return (((
char *)
data) + data_size * idx);
11891 return "<unknown>";
11921 if (data_str == NULL)
11925 if (strncmp(data_str,
"0x", 2) == 0) {
11927 sscanf(data_str + 2,
"%x", &
value);
11936 *((
char *)
data +
i) = (char) atoi(data_str);
11939 *((
char *)
data +
i) = data_str[0];
11949 *((
short int *)
data +
i) = (
short int)
value;
11951 *((
short int *)
data +
i) = (
short int) atoi(data_str);
11955 value = strtoul(data_str,
nullptr, 16);
11957 value = strtoul(data_str,
nullptr, 10);
11963 value = strtol(data_str,
nullptr, 16);
11965 value = strtol(data_str,
nullptr, 10);
11971 *((
UINT64 *)
data +
i) = strtoull(data_str,
nullptr, 16);
11973 *((
UINT64 *)
data +
i) = strtoull(data_str,
nullptr, 10);
11977 *((
UINT64 *)
data +
i) = strtoll(data_str,
nullptr, 16);
11979 *((
UINT64 *)
data +
i) = strtoll(data_str,
nullptr, 10);
11982 if (data_str[0] ==
'y' || data_str[0] ==
'Y' ||
11983 data_str[0] ==
't' || data_str[0] ==
'T' || atoi(data_str) > 0)
11989 if (data_str[0] ==
'n' || data_str[0] ==
'N')
11992 *((
float *)
data +
i) = (float) atof(data_str);
11995 if (data_str[0] ==
'n' || data_str[0] ==
'N')
11998 *((
double *)
data +
i) = atof(data_str);
12002 value = strtoul(data_str,
nullptr, 16);
12004 value = strtoul(data_str,
nullptr, 10);
12010 strcpy((
char *)
data, data_str);
12011 *data_size = strlen(data_str) + 1;
12020#ifdef LOCAL_ROUTINES
12033 INT size, align, corr, total_size_tmp;
12043 pkey = (
const KEY *) ((
char *) pheader + pkeylist->
first_key);
12070 if (max_align && align > *max_align)
12071 *max_align = align;
12073 corr =
VALIGN(*total_size, align) - *total_size;
12074 *total_size += corr;
12076 *
data = (
void *) ((
char *) (*data) + corr);
12083 KEY* wpkey = (
KEY*)pkey;
12089 if (convert_flags) {
12109 if (convert_flags) {
12123 *total_size += size;
12129 total_size_tmp = *total_size;
12132 if (max_align && align > *max_align)
12133 *max_align = align;
12135 corr =
VALIGN(*total_size, align) - *total_size;
12136 *total_size += corr;
12138 *
data = (
void *) ((
char *) (*data) + corr);
12143 corr =
VALIGN(*total_size, align) - *total_size;
12144 *total_size += corr;
12146 *
data = (
void *) ((
char *) (*data) + corr);
12158 pkey = (
KEY *) ((
char *) pheader + pkey->
next_key);
12207#ifdef LOCAL_ROUTINES
12232 *buf_size = max_align = 0;
12237 *buf_size =
VALIGN(*buf_size, max_align);
12303#ifdef LOCAL_ROUTINES
12310 if (
data && buf_size) {
12311 memset(
data, 0x00, *buf_size);
12333 cm_msg(
MERROR,
"db_get_record",
"struct size mismatch for \"%s\" (expected size: %d, size in ODB: %d * %d = %d)",
12340 if (convert_flags) {
12352 if (total_size != *buf_size) {
12353 cm_msg(
MERROR,
"db_get_record",
"struct size mismatch for \"%s\" (expected size: %d, size in ODB: %d)",
db_get_path(
hDB,
hKey).c_str(), *buf_size, total_size);
12397 int size = *buf_size;
12412 cm_msg(
MINFO,
"db_get_record1",
"Fixing ODB \"%s\" struct size mismatch (expected %d, odb size %d)", path.c_str(), size,
odb_size);
12442 cm_msg(
MERROR,
"db_get_record1",
"after db_check_record() still struct size mismatch (expected %d, odb size %d) of \"%s\", calling db_create_record()", size,
odb_size, path.c_str());
12448 cm_msg(
MERROR,
"db_get_record1",
"repaired struct size mismatch of \"%s\"", path.c_str());
12456static int db_parse_record(
const char* rec_str,
const char** out_rec_str,
char* title,
int title_size,
char* key_name,
int key_name_size,
int* tid,
int* n_data,
int* string_length)
12462 *string_length = 0;
12463 *out_rec_str = NULL;
12477 while (*rec_str ==
'\n')
12481 if (rec_str[0] ==
'[') {
12487 mstrlcpy(title, rec_str, title_size);
12488 char* p = strchr(title,
']');
12492 int len = strlen(title);
12494 if (title[len - 1] !=
'/')
12495 mstrlcat(title,
"/", title_size);
12499 const char* pend = strchr(rec_str,
'\n');
12503 rec_str = rec_str+strlen(rec_str);
12505 while (*rec_str ==
'\n')
12508 *out_rec_str = rec_str;
12512 if (rec_str[0] ==
';') {
12514 const char* pend = strchr(rec_str,
'\n');
12518 rec_str = rec_str+strlen(rec_str);
12520 while (*rec_str ==
'\n')
12523 *out_rec_str = rec_str;
12527 const char* peq = strchr(rec_str,
'=');
12529 cm_msg(
MERROR,
"db_parse_record",
"do not see \'=\'");
12533 int key_name_len = peq - rec_str;
12536 while (key_name_len > 1) {
12537 if (rec_str[key_name_len-1] ==
'=') {
12541 if (rec_str[key_name_len-1] ==
' ') {
12548 memcpy(key_name, rec_str, key_name_len);
12549 key_name[key_name_len] = 0;
12553 while (*rec_str ==
' ')
12559 for (
i=0;
i<(int)
sizeof(stid)-1;
i++) {
12562 if (s ==
' ')
break;
12563 if (s ==
'\n')
break;
12564 if (s ==
'[')
break;
12571 for (xtid = 0; xtid <
TID_LAST; xtid++) {
12581 cm_msg(
MERROR,
"db_parse_record",
"do not see \':\'");
12585 while (*rec_str ==
' ')
12590 if (*rec_str ==
'[') {
12593 *n_data = atoi(rec_str);
12594 const char *pbr = strchr(rec_str,
']');
12596 cm_msg(
MERROR,
"db_parse_record",
"do not see closing bracket \']\'");
12602 while (*rec_str ==
' ')
12605 const char* pcol = strchr(rec_str,
':');
12607 cm_msg(
MERROR,
"db_parse_record",
"do not see \':\'");
12611 rec_str = pcol + 1;
12613 while (*rec_str ==
' ')
12616 *string_length = 0;
12619 const char* pbr = strchr(rec_str,
'[');
12621 *string_length = atoi(pbr+1);
12626 const char* pend = strchr(rec_str,
'\n');
12630 rec_str = rec_str+strlen(rec_str);
12632 while (*rec_str ==
'\n')
12635 *out_rec_str = rec_str;
12642 assert(n_data > 0);
12644 int offset = *buf_ptr - buf_start;
12646 if (tsize && (
offset%tsize != 0)) {
12647 while (
offset%tsize != 0) {
12649 *(*buf_ptr) = 0xFF;
12655 printf(
"read element [%s] tid %d, n_data %d, string_length %d, tid_size %d, align %d, offset %d, buf_remain %d\n", key_name, tid, n_data, string_length, tsize, align,
offset, *buf_remain);
12657 int xsize = tsize*n_data;
12658 if (xsize > *buf_remain) {
12659 cm_msg(
MERROR,
"db_get_record2",
"buffer overrun at key \"%s\", size %d, buffer remaining %d", key_name, xsize, *buf_remain);
12666 cm_msg(
MERROR,
"db_get_record2",
"cannot read \"%s\", db_get_value() status %d", key_name,
status);
12667 memset(*buf_ptr, 0, xsize);
12669 *buf_remain -= xsize;
12673 *buf_remain -= xsize;
12677 for (
i=0;
i<n_data;
i++) {
12678 int xsize = string_length;
12679 if (xsize > *buf_remain) {
12680 cm_msg(
MERROR,
"db_get_record2",
"string buffer overrun at key \"%s\" index %d, size %d, buffer remaining %d", key_name,
i, xsize, *buf_remain);
12683 std::string xkey_name =
msprintf(
"%s[%d]", key_name,
i);
12688 (*buf_ptr)[string_length-1] = 0;
12689 cm_msg(
MERROR,
"db_get_record2",
"string key \"%s\" index %d, string value was truncated", key_name,
i);
12691 cm_msg(
MERROR,
"db_get_record2",
"cannot read string \"%s\"[%d], db_get_value() status %d", key_name,
i,
status);
12692 memset(*buf_ptr, 0, string_length);
12695 *buf_ptr += string_length;
12696 *buf_remain -= string_length;
12698 if (xstatus != 0) {
12702 cm_msg(
MERROR,
"db_get_record2",
"cannot read key \"%s\" of unsupported type %d", key_name, tid);
12762 printf(
"db_get_record2!\n");
12764 assert(
data != NULL);
12765 assert(xbuf_size != NULL);
12766 assert(*xbuf_size > 0);
12767 assert(correct == 0);
12772 int rs = *xbuf_size;
12774 r1 = (
char*)malloc(rs);
12775 assert(r1 != NULL);
12776 memset(
data, 0xFF, *xbuf_size);
12777 memset(r1, 0xFF, rs);
12780 printf(
"db_get_record status %d\n",
status);
12784 char* buf_start = (
char*)
data;
12785 int buf_size = *xbuf_size;
12787 char* buf_ptr = buf_start;
12788 int buf_remain = buf_size;
12790 while (rec_str && *rec_str != 0) {
12795 int string_length = 0;
12796 const char* rec_str_next = NULL;
12798 status =
db_parse_record(rec_str, &rec_str_next, title,
sizeof(title), key_name,
sizeof(key_name), &tid, &n_data, &string_length);
12802 rec_str = rec_str_next;
12808 if (key_name[0] == 0) {
12815 cm_msg(
MERROR,
"db_get_record2",
"error: cannot continue reading odb record because of previous fatal error, status %d",
status);
12821 rec_str = rec_str_next;
12827 for (
i=0;
i<rs;
i++) {
12828 if (r1[
i] != buf_start[
i]) {
12833 if (ok>=0 || buf_remain>0) {
12834 printf(
"db_get_record2: miscompare at %d out of %d, buf_remain %d\n", ok, rs, buf_remain);
12836 printf(
"db_get_record2: check ok\n");
12840 if (buf_remain > 0) {
12887#ifdef LOCAL_ROUTINES
12914 if (convert_flags) {
12927 if (total_size != buf_size) {
12951#ifndef DOXYGEN_SHOULD_SKIP_THIS
12966#ifdef LOCAL_ROUTINES
12972 cm_msg(
MERROR,
"db_add_open_record",
"invalid database handle");
12991 if (i < pclient->max_index) {
13041#ifdef LOCAL_ROUTINES
13051 for (idx = 0; idx < pclient->
max_index; idx++)
13103#ifdef LOCAL_ROUTINES
13106 cm_msg(
MERROR,
"db_remove_open_record",
"invalid database handle %d",
hDB);
13128#ifdef LOCAL_ROUTINES
13195 cm_msg(
MERROR,
"db_notify_clients",
"db_notify_clients() does not work in remotely connected MIDAS clients");
13199#ifdef LOCAL_ROUTINES
13231#ifdef LOCAL_ROUTINES
13263 mstrlcpy(full_name, s.c_str(),
sizeof(full_name));
13264 *strchr(full_name,
'O') =
'I';
13271 cm_msg(
MERROR,
"merge_records",
"merge_record error at \'%s\', db_get_key() status %d", full_name,
status);
13276 cm_msg(
MERROR,
"merge_records",
"merge_record error at \'%s\', second db_get_key() status %d", full_name,
status);
13281 char* allocbuffer = NULL;
13282 char stackbuffer[10000];
13283 char* buffer = stackbuffer;
13284 size =
sizeof(stackbuffer);
13291 cm_msg(
MERROR,
"merge_records",
"merge_record error at \'%s\', db_set_data() status %d", full_name,
status);
13298 allocbuffer = (
char *)realloc(allocbuffer, size);
13299 assert(allocbuffer != NULL);
13300 buffer = allocbuffer;
13303 cm_msg(
MERROR,
"merge_records",
"aborting on unexpected failure of db_get_data(%s), status %d", full_name,
status);
13314 size =
sizeof(full_name);
13317 cm_msg(
MERROR,
"merge_records",
"Invalid link \"%s\"", full_name);
13319 cm_msg(
MERROR,
"merge_records",
"aborting on unexpected failure of db_find_key(%s), status %d", full_name,
status);
13394 char key_name[256], *buffer;
13405 mstrlcpy(key_name, orig_key_name,
sizeof(key_name));
13406 if (strlen(key_name) > 1 && key_name[strlen(key_name) - 1] ==
'/')
13407 key_name[strlen(key_name) - 1] = 0;
13412 assert(hKeyOrig != 0);
13413#ifdef CHECK_OPEN_RECORD
13449 buffer_size = 10000;
13450 buffer = (
char *) malloc(buffer_size);
13451 assert(buffer != NULL);
13454 size = buffer_size;
13457 buffer_size += 10000;
13458 buffer = (
char *) realloc(buffer, buffer_size);
13459 assert(buffer != NULL);
13496 size = buffer_size;
13499 buffer_size += 10000;
13500 buffer = (
char *) realloc(buffer, buffer_size);
13539 cm_msg(
MERROR,
"db_create_record",
"aborting on unexpected failure of db_find_key(%s), status %d", key_name,
status);
13571 const char *pold, *rec_str_orig;
13574 HNDLE hKeyRoot, hKeyTest;
13576 int bad_string_length;
13594 rec_str_orig = rec_str;
13602 hKeyTest = hKeyRoot;
13604 if (hKeyTest == 0 && *rec_str != 0) {
13616 line[
i] = *rec_str++;
13624 if (*rec_str ==
'\n')
13628 if (line[0] ==
'[') {
13630 strcpy(title, line + 1);
13631 if (strchr(title,
']'))
13632 *strchr(title,
']') = 0;
13633 if (title[0] && title[strlen(title) - 1] !=
'/')
13634 strcat(title,
"/");
13637 if (strchr(line,
'=') && line[0] !=
';') {
13639 pc = strchr(line,
'=') + 1;
13642 strcpy(info_str, pc);
13645 *strchr(line,
'=') = 0;
13647 pc = &line[strlen(line) - 1];
13651 mstrlcpy(key_name, line,
sizeof(key_name));
13654 strcpy(line, info_str);
13655 if (strchr(line,
' '))
13656 *strchr(line,
' ') = 0;
13659 if (strchr(line,
'[')) {
13660 n_data = atol(strchr(line,
'[') + 1);
13661 *strchr(line,
'[') = 0;
13664 for (tid = 0; tid <
TID_LAST; tid++)
13668 for (tid = 0; tid <
TID_LAST; tid++)
13676 cm_msg(
MERROR,
"db_check_record",
"found unknown data type \"%s\" in ODB file", line);
13680 while (*pc !=
' ' && *pc)
13682 while ((*pc ==
' ' || *pc ==
':') && *pc)
13690 for (
j = 0; *rec_str !=
'\n' && *rec_str;
j++)
13691 info_str[
j] = *rec_str++;
13693 if (*rec_str ==
'\n')
13697 for (
i = 0;
i < n_data;
i++) {
13699 pc = &info_str[strlen(info_str) - 1];
13700 while (*pc ==
'\n' || *pc ==
'\r')
13704 if (!string_length) {
13705 if (info_str[1] ==
'=')
13706 string_length = -1;
13708 pc = strchr(info_str,
'[');
13710 string_length = atoi(pc + 1);
13712 string_length = -1;
13716 cm_msg(
MERROR,
"db_check_record",
"found string exceeding MAX_STRING_LENGTH");
13720 if (string_length == -1) {
13722 if (strstr(rec_str,
"\n====#$@$#====\n") != NULL) {
13723 string_length = (
POINTER_T) strstr(rec_str,
"\n====#$@$#====\n") - (
POINTER_T) rec_str + 1;
13725 rec_str = strstr(rec_str,
"\n====#$@$#====\n") + strlen(
"\n====#$@$#====\n");
13727 cm_msg(
MERROR,
"db_check_record",
"found multi-line string without termination sequence");
13729 if (strchr(info_str,
']'))
13730 pc = strchr(info_str,
']') + 1;
13733 while (*pc && *pc !=
' ')
13735 while (*pc && *pc ==
' ')
13739 *(pc + string_length - 1) = 0;
13744 if (n_data > 1 && info_str[0] ==
'[') {
13745 pc = strchr(info_str,
']') + 1;
13746 while (*pc && *pc ==
' ')
13751 if (
i < n_data - 1) {
13758 for (
j = 0; *rec_str !=
'\n' && *rec_str;
j++)
13759 info_str[
j] = *rec_str++;
13761 if (*rec_str ==
'\n')
13766 if (info_str[0] == 0 || (strchr(info_str,
'=')
13767 && strchr(info_str,
':')))
13784 bad_string_length = 0;
13788 if (string_length > 0 && string_length !=
key.
item_size) {
13789 bad_string_length = 1;
13884 WORD access_mode,
void (*dispatcher) (
INT,
INT,
void *),
void *
info)
13896 cm_msg(
MERROR,
"db_open_record",
"not enough memory");
13912 cm_msg(
MERROR,
"db_open_record",
"not enough memory");
13928 cm_msg(
MERROR,
"db_open_record",
"cannot get record size, db_get_record_size() status %d",
status);
13932 if (size != rec_size && ptr != NULL) {
13935 cm_msg(
MERROR,
"db_open_record",
"struct size mismatch for \"%s\" (expected size: %d, size in ODB: %d)", path.c_str(), rec_size, size);
13948 data = malloc(size);
13950 if (
data == NULL) {
13952 cm_msg(
MERROR,
"db_open_record",
"not enough memory, malloc(%d) returned NULL", size);
13956 memset(
data, 0, size);
13958 *((
void **) ptr) =
data;
13968 cm_msg(
MERROR,
"db_open_record",
"cannot get record, db_get_record() status %d",
status);
13980 cm_msg(
MERROR,
"db_open_record",
"cannot set record, db_set_record() status %d",
status);
13988 cm_msg(
MERROR,
"db_open_record",
"not enough memory");
14035 WORD access_mode,
void (*dispatcher) (
INT,
INT,
void *),
void *
info,
14036 const char *rec_str)
14042 int size = rec_size;
14043 pbuf = (
char*)malloc(size);
14044 assert(pbuf != NULL);
14068#ifdef LOCAL_ROUTINES
14203 *((
INT *) nc->
param + 1) = hKeyRoot;
14207 if (convert_flags) {
14451 cm_msg(
MERROR,
"db_watch",
"cannot get key \"%s\"", path.c_str());
14459 cm_msg(
MERROR,
"db_watch",
"cannot get key \"%s\"", path.c_str());
14483#ifdef LOCAL_ROUTINES
14536 cm_msg(
MERROR,
"db_get_value_string",
"cannot resize odb string arrays, please use db_resize_string() instead");
14555 char* buf = (
char*)malloc(size);
14556 assert(buf != NULL);
14579 if (create_string_length == 0) {
14580 int size = s->length() + 1;
14583 char* buf = (
char*)malloc(create_string_length);
14585 mstrlcpy(buf, s->c_str(), create_string_length);
14602 int size = s->length() + 1;
14626 int old_num_values = 0;
14627 int old_item_size = 0;
14629 char* old_data = NULL;
14644 old_size = old_num_values * old_item_size;
14645 if (old_size > 0) {
14646 old_data = (
char*)malloc(old_size);
14647 assert(old_data != NULL);
14648 int size = old_size;
14654 assert(size == old_size);
14667 int item_size = max_string_length;
14670 item_size = old_item_size;
14672 if (num_values < 1)
14673 num_values = old_num_values;
14675 int new_size = num_values * item_size;
14676 char* new_data = (
char*)malloc(new_size);
14679 memset(new_data, 0, new_size);
14682 int num = old_num_values;
14683 if (num > num_values)
14688 for (
int i=0;
i<num;
i++) {
14689 const char* old_ptr = old_data +
i*old_item_size;
14690 char* new_ptr = new_data +
i*item_size;
14691 mstrlcpy(new_ptr, old_ptr, item_size);
14707#ifdef LOCAL_ROUTINES
14708 MJsonNode* scl = MJsonNode::MakeObject();
14709 MJsonNode* clients = MJsonNode::MakeArray();
14711 scl->AddToObject(
"now", MJsonNode::MakeNumber(
ss_time_sec()));
14712 scl->AddToObject(
"clients", clients);
14725 if (pclient->
pid) {
14726 MJsonNode*
c = MJsonNode::MakeObject();
14727 c->AddToObject(
"slot", MJsonNode::MakeNumber(
i));
14728 c->AddToObject(
"pid", MJsonNode::MakeNumber(pclient->
pid));
14729 c->AddToObject(
"name", MJsonNode::MakeString(pclient->
name));
14730 std::string path =
msprintf(
"/System/Clients/%d/Host", pclient->
pid);
14734 char* host = (
char*)malloc(host_size);
14735 assert(host != NULL);
14737 c->AddToObject(
"host", MJsonNode::MakeString(host));
14740 c->AddToObject(
"watchdog_timeout_millisec", MJsonNode::MakeNumber(pclient->
watchdog_timeout));
14742 c->AddToObject(
"last_activity_millisec", MJsonNode::MakeNumber(now - pclient->
last_activity));
14743 clients->AddToArray(
c);
14751 return MJsonNode::MakeNull();
14758 assert(root_path != NULL);
14759#ifdef LOCAL_ROUTINES
14760 size_t root_path_len = strlen(root_path);
14761 MJsonNode* sor = MJsonNode::MakeArray();
14772 if (pclient->
pid) {
14775 if (path.length() < root_path_len)
14777 if (strncmp(root_path, path.c_str(), root_path_len) != 0)
14779 MJsonNode*
c = MJsonNode::MakeObject();
14780 c->AddToObject(
"name", MJsonNode::MakeString(pclient->
name));
14784 c->AddToObject(
"path", MJsonNode::MakeString(path.c_str()));
14785 sor->AddToArray(
c);
14794 return MJsonNode::MakeNull();
INT cm_get_watchdog_params(BOOL *call_watchdog, DWORD *timeout)
#define DB_STRUCT_MISMATCH
#define DB_INVALID_HANDLE
#define DB_STRUCT_SIZE_MISMATCH
#define DB_NO_MORE_SUBKEYS
#define DB_VERSION_MISMATCH
#define VALIGN(adr, align)
#define MAX_STRING_LENGTH
INT ss_get_struct_align()
INT ss_suspend_get_odb_port(INT *port)
bool ss_is_valid_utf8(const char *string)
INT ss_mutex_release(MUTEX_T *mutex)
INT ss_shm_flush(const char *name, const void *adr, size_t size, HNDLE handle, bool wait_for_thread)
INT ss_semaphore_create(const char *name, HNDLE *semaphore_handle)
INT ss_mutex_delete(MUTEX_T *mutex)
INT ss_mutex_create(MUTEX_T **mutex, BOOL recursive)
INT ss_shm_open(const char *name, INT size, void **adr, size_t *shm_size, HNDLE *handle, BOOL get_size)
INT ss_semaphore_release(HNDLE semaphore_handle)
void ss_stack_history_entry(char *tag)
std::string ss_tid_to_string(midas_thread_t thread_id)
INT ss_resume(INT port, const char *message)
midas_thread_t ss_gettid(void)
INT ss_semaphore_delete(HNDLE semaphore_handle, INT destroy_flag)
INT ss_semaphore_wait_for(HNDLE semaphore_handle, DWORD timeout_millisec)
INT ss_shm_unprotect(HNDLE handle, void **adr, size_t shm_size, BOOL read, BOOL write, const char *caller_name)
INT ss_shm_close(const char *name, void *adr, size_t shm_size, HNDLE handle, INT destroy_flag)
INT send_tcp(int sock, char *buffer, DWORD buffer_size, INT flags)
BOOL ss_pid_exists(int pid)
INT ss_shm_protect(HNDLE handle, void *adr, size_t shm_size)
INT ss_mutex_wait_for(MUTEX_T *mutex, INT timeout)
INT cm_msg_flush_buffer()
INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
BOOL equal_ustring(const char *str1, const char *str2)
static void free_key(DATABASE_HEADER *pheader, void *address, INT size)
INT db_sprintfh(char *string, const void *data, INT data_size, INT idx, DWORD type)
INT db_flush_database(HNDLE hDB)
bool operator<(const keylist_struct &a, const keylist_struct &b)
static void json_write_key(HNDLE hDB, HNDLE hKey, const KEY *key, const char *link_path, char **buffer, int *buffer_size, int *buffer_end)
INT db_remove_open_record(HNDLE hDB, HNDLE hKey, BOOL lock)
static void check_open_keys(HNDLE hDB, HNDLE hKey, KEY *pkey, INT level, void *info)
INT db_get_data_index(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT idx, DWORD type)
INT db_delete_key(HNDLE hDB, HNDLE hKey, BOOL follow_links)
INT db_send_changed_records()
INT db_find_link(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
INT db_check_client(HNDLE hDB, HNDLE hKeyClient)
static void * malloc_key(DATABASE_HEADER *pheader, INT size, const char *caller)
static INT db_set_data_index_wlocked(DATABASE_HEADER *pheader, KEY *pkey, int idx, const void *data, INT data_size, DWORD type, const char *caller, db_err_msg **msg)
INT db_get_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, void *data, INT *buf_size, DWORD type, BOOL create)
INT db_reorder_key(HNDLE hDB, HNDLE hKey, INT idx)
static const KEY * db_get_parent(const DATABASE_HEADER *pheader, const KEY *pkey, int *pstatus, const char *caller, db_err_msg **msg)
static int db_scan_tree_locked(const DATABASE_HEADER *pheader, const KEY *pkey, int level, int(*callback)(const DATABASE_HEADER *, const KEY *, int, void *, db_err_msg **), void *info, db_err_msg **msg)
INT db_save_json(HNDLE hDB, HNDLE hKey, const char *filename, int flags)
static INT _record_list_entries
INT db_open_record(HNDLE hDB, HNDLE hKey, void *ptr, INT rec_size, WORD access_mode, void(*dispatcher)(INT, INT, void *), void *info)
INT db_open_database(const char *xdatabase_name, INT database_size, HNDLE *hDB, const char *client_name)
static int db_paste_node(HNDLE hDB, HNDLE hKeyRoot, PMXML_NODE node)
INT db_get_open_records(HNDLE hDB, HNDLE hKey, char *str, INT buf_size, BOOL fix)
INT db_paste_xml(HNDLE hDB, HNDLE hKeyRoot, const char *buffer)
static INT db_check_set_data_locked(DATABASE_HEADER *pheader, const KEY *pkey, const void *data, INT data_size, INT num_values, DWORD type, const char *caller, db_err_msg **msg)
void db_cleanup(const char *who, DWORD actual_time, BOOL wrong_interval)
static const KEY * db_resolve_link_locked(const DATABASE_HEADER *, const KEY *, int *pstatus, db_err_msg **)
static bool db_validate_hkey(const DATABASE_HEADER *pheader, HNDLE hKey)
std::string strcomb1(const char **list)
static void db_print_hkey(const DATABASE_HEADER *pheader, HNDLE hkey, int recurse=0, const char *path=NULL, HNDLE parenthkeylist=0)
static void * malloc_data(DATABASE_HEADER *pheader, INT size)
static int db_save_json_key_obsolete(HNDLE hDB, HNDLE hKey, INT level, char **buffer, int *buffer_size, int *buffer_end, int save_keys, int follow_links, int recurse)
INT db_save_xml(HNDLE hDB, HNDLE hKey, const char *filename)
static int db_delete_key_locked(DATABASE *pdb, const KEY *pkey, int level, db_err_msg **msg)
INT db_set_link_data(HNDLE hDB, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type)
static INT print_key_info_locked(const DATABASE_HEADER *pheader, const KEY *pkey, INT level, void *info, db_err_msg **msg)
static const KEY * db_find_pkey_locked(const DATABASE_HEADER *pheader, const KEY *pkey, const char *key_name, bool follow_links, int *pstatus, db_err_msg **msg)
INT db_get_path(HNDLE hDB, HNDLE hKey, char *path, INT buf_size)
static bool check_free_list_repair(db_err_msg **msg)
int json_write_bare_subdir(HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end, int level, int flags, time_t timestamp)
INT db_get_record1(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT align, const char *rec_str)
static int db_create_key_wlocked(DATABASE_HEADER *pheader, KEY *parentKey, const char *key_name, DWORD type, KEY **pnewkey, db_err_msg **msg)
INT db_copy(HNDLE hDB, HNDLE hKey, char *buffer, INT *buffer_size, const char *path)
INT db_set_link_data_index(HNDLE hDB, HNDLE hKey, const void *data, INT data_size, INT idx, DWORD type)
BOOL strmatch(char *pattern, char *str)
INT EXPRT db_enum(HNDLE hDB, HNDLE hKeyRoot, std::vector< HNDLE > *sub_handles, std::vector< KEY > *sub_keys, bool follow_links)
std::string db_show_mem(HNDLE hDB, BOOL verbose)
INT db_get_record_size(HNDLE hDB, HNDLE hKey, INT align, INT *buf_size)
static INT db_check_set_data_index_locked(DATABASE_HEADER *pheader, const KEY *pkey, int idx, const void *data, INT data_size, DWORD type, const char *caller, db_err_msg **msg)
static INT db_get_data_locked(DATABASE_HEADER *pheader, const KEY *pkey, int idx, void *data, INT *buf_size, DWORD type, db_err_msg **msg)
INT db_get_data(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, DWORD type)
INT db_create_key(HNDLE hDB, HNDLE hKey, const char *key_name, DWORD type)
INT db_check_record(HNDLE hDB, HNDLE hKey, const char *keyname, const char *rec_str, BOOL correct)
static int validate_free_data(DATABASE_HEADER *pheader, int free_data)
static bool db_validate_and_repair_key_wlocked(DATABASE_HEADER *pheader, int recurse, const char *path, HNDLE parenthkeylist, HNDLE hkey, KEY *pkey, db_err_msg **msg, keylist_vector *keylist)
INT db_copy_json_save(HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end)
INT db_copy_xml(HNDLE hDB, HNDLE hKey, char *buffer, int *buffer_size, bool header)
MJsonNode * db_scl(HNDLE hDB)
static RECORD_LIST * _record_list
INT db_save_struct(HNDLE hDB, HNDLE hKey, const char *file_name, const char *struct_name, BOOL append)
INT db_get_record(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT align)
static void * realloc_data(DATABASE_HEADER *pheader, void *address, INT old_size, INT new_size, const char *caller)
void xml_encode(char *src, int size)
INT db_unwatch(HNDLE hDB, HNDLE hKey)
INT db_set_mode(HNDLE hDB, HNDLE hKey, WORD mode, BOOL recurse)
INT db_get_next_link(HNDLE hDB, HNDLE hKey, HNDLE *subkey_handle)
static bool db_validate_data_area_wlocked(DATABASE_HEADER *pheader, const keylist_vector &keylist, const keylist_vector &datafreelist, db_err_msg **msg)
static const KEYLIST * db_get_pkeylist(const DATABASE_HEADER *pheader, const KEY *pkey, const char *caller, db_err_msg **msg, bool kludge_repair=false)
INT db_scan_tree_link(HNDLE hDB, HNDLE hKey, INT level, void(*callback)(HNDLE, HNDLE, KEY *, INT, void *), void *info)
INT db_save(HNDLE hDB, HNDLE hKey, const char *filename, BOOL bRemote)
static bool db_validate_and_repair_db_wlocked(DATABASE_HEADER *pheader, db_err_msg **msg)
INT db_allow_write_locked(DATABASE *p, const char *caller_name)
INT db_scan_tree(HNDLE hDB, HNDLE hKey, INT level, INT(*callback)(HNDLE, HNDLE, KEY *, INT, void *), void *info)
INT db_get_key(HNDLE hDB, HNDLE hKey, KEY *key)
static bool db_get_key_free_list_locked(const DATABASE_HEADER *pheader, keylist_vector *keyfreelist, db_err_msg **msg)
static INT db_get_key_locked(const DATABASE_HEADER *pheader, HNDLE hKey, KEY *key, db_err_msg **msg)
static int _global_open_count
INT db_get_link(HNDLE hDB, HNDLE hKey, KEY *key)
static INT _database_entries
static bool db_validate_data_offset(const DATABASE_HEADER *pheader, int offset)
static int db_remove_open_record_wlocked(DATABASE *pdb, DATABASE_HEADER *pheader, HNDLE hKey)
static int json_write_bare_key(HNDLE hDB, HNDLE hLink, const KEY &link, char **buffer, int *buffer_size, int *buffer_end, int level, int flags, time_t timestamp, bool need_comma)
static int db_get_record2_read_element(HNDLE hDB, HNDLE hKey, const char *key_name, int tid, int n_data, int string_length, char *buf_start, char **buf_ptr, int *buf_remain, BOOL correct)
INT db_load(HNDLE hDB, HNDLE hKeyRoot, const char *filename, BOOL bRemote)
INT EXPRT db_get_value_string(HNDLE hdb, HNDLE hKeyRoot, const char *key_name, int index, std::string *s, BOOL create, int create_string_length)
INT db_sprintff(char *string, const char *format, const void *data, INT data_size, INT idx, DWORD type)
static void db_delete_client_wlocked(DATABASE_HEADER *pheader, int jclient, db_err_msg **msg)
INT db_get_watchdog_info(HNDLE hDB, const char *client_name, DWORD *timeout, DWORD *last)
INT db_set_data_index(HNDLE hDB, HNDLE hKey, const void *data, INT data_size, INT idx, DWORD type)
static int db_notify_clients_locked(const DATABASE *pdb, HNDLE hKeyMod, int index, BOOL bWalk, db_err_msg **msg)
static HNDLE db_pkey_to_hkey(const DATABASE_HEADER *pheader, const KEY *pkey)
static bool db_validate_key_offset(const DATABASE_HEADER *pheader, int offset)
static int free_data(DATABASE_HEADER *pheader, void *address, INT size, const char *caller)
static void db_save_tree_struct(HNDLE hDB, HNDLE hKey, int hfile, INT level)
static void db_print_pkey(const DATABASE_HEADER *pheader, const KEY *pkey, int recurse=0, const char *path=NULL, HNDLE parenthkeylist=0)
INT db_save_string(HNDLE hDB, HNDLE hKey, const char *file_name, const char *string_name, BOOL append)
static int db_update_open_record_wlocked(const DATABASE_HEADER *xpheader, const KEY *xpkey, int level, void *voidp, db_err_msg **msg)
INT db_copy_json_index(HNDLE hDB, HNDLE hKey, int index, char **buffer, int *buffer_size, int *buffer_end)
static int db_check_open_record(const DATABASE_HEADER *pheader, const KEY *pkey, db_err_msg **msg)
INT db_close_all_records()
static int db_delete_client_info_wlocked(DATABASE *pdb, int pid, db_err_msg **msg)
static const KEY * db_enum_next_locked(const DATABASE_HEADER *pheader, const KEY *pdir, const KEY *pkey, db_err_msg **msg)
INT db_paste(HNDLE hDB, HNDLE hKeyRoot, const char *buffer)
INT db_save_xml_key(HNDLE hDB, HNDLE hKey, INT level, MXML_WRITER *writer)
static std::string db_get_path_pkey(const DATABASE_HEADER *pheader, const KEY *pkey)
static void static void db_print_msg(const db_err_msg *msg)
INT db_watch(HNDLE hDB, HNDLE hKey, void(*dispatcher)(INT, INT, INT, void *), void *info)
static std::string db_get_path_locked(const DATABASE_HEADER *pheader, HNDLE hKey)
INT db_get_key_info(HNDLE hDB, HNDLE hKey, char *name, INT name_size, INT *type, INT *num_values, INT *item_size)
INT db_close_all_databases(void)
INT db_set_data(HNDLE hDB, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type)
INT db_enum_link(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
static const KEY * db_get_pkey(const DATABASE_HEADER *pheader, HNDLE hKey, int *pstatus, const char *caller, db_err_msg **msg)
INT db_copy_json_ls(HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end)
char * strcomb(const char **list)
static INT db_set_data_wlocked(DATABASE_HEADER *pheader, KEY *pkey, const void *data, INT data_size, INT num_values, DWORD type, const char *caller, db_err_msg **msg)
int EXPRT json_write_anything(HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end, int level, int must_be_subdir, int flags, time_t timestamp)
static WATCH_LIST * _watch_list
static int db_fix_open_records(HNDLE hDB, HNDLE hKey, KEY *key, INT level, void *xresult)
INT db_delete(HNDLE hDB, HNDLE hKeyRoot, const char *odb_path)
INT db_sprintf(char *string, const void *data, INT data_size, INT idx, DWORD type)
INT db_update_last_activity(DWORD millitime)
INT db_copy_json_obsolete(HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end, int save_keys, int follow_links, int recurse)
INT db_get_free_mem(HNDLE hDB, size_t *pkey_size, size_t *pdata_size, size_t *pdata_biggest)
void strarrayindex(char *odbpath, int *index1, int *index2)
INT db_set_data1(HNDLE hDB, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type)
DATABASE_CLIENT * db_get_my_client_locked(DATABASE *pdb)
static int db_set_mode_wlocked(DATABASE_HEADER *, KEY *, WORD mode, int recurse, db_err_msg **)
INT db_get_data1(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, DWORD type, INT *num_values)
INT db_copy_json_values(HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end, int omit_names, int omit_last_written, time_t omit_old_timestamp, int preserve_case)
INT db_set_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, const void *data, INT data_size, INT num_values, DWORD type)
static int db_find_open_records(HNDLE hDB, HNDLE hKey, KEY *key, INT level, void *xresult)
static void json_write_data(char **buffer, int *buffer_size, int *buffer_end, int level, const KEY *key, const char *p)
static INT _watch_list_entries
INT db_find_key(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
static void db_recurse_record_tree_locked(const DATABASE *pdb, const KEY *pkey, void **data, INT *total_size, INT base_align, INT *max_align, BOOL bSet, INT convert_flags, db_err_msg **msg)
static const KEY * db_enum_first_locked(const DATABASE_HEADER *pheader, const KEY *pkey, db_err_msg **msg)
INT db_update_record_local(INT hDB, INT hKeyRoot, INT hKey, int index)
INT db_copy_json_array(HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end)
MJsonNode * db_sor(HNDLE hDB, const char *root_path)
INT db_get_link_data(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, DWORD type)
void db_set_watchdog_params(DWORD timeout)
static void db_validate_sizes()
INT db_update_record_mserver(INT hDB, INT hKeyRoot, INT hKey, int index, int client_socket)
INT db_rename_key(HNDLE hDB, HNDLE hKey, const char *name)
BOOL ends_with_ustring(const char *str, const char *suffix)
void db_cleanup2(const char *client_name, int ignore_timeout, DWORD actual_time, const char *who)
void json_write(char **buffer, int *buffer_size, int *buffer_end, int level, const char *s, int quoted)
INT EXPRT db_paste_json(HNDLE hDB, HNDLE hKeyRoot, const char *buffer)
static bool is_utf8(const char *string)
INT db_get_key_time(HNDLE hDB, HNDLE hKey, DWORD *delta)
int db_delete_client_info(HNDLE hDB, int pid)
static bool db_validate_key_area_wlocked(DATABASE_HEADER *pheader, const keylist_vector &keylist, const keylist_vector &keyfreelist, db_err_msg **msg)
static void db_flush_msg(db_err_msg **msg)
static INT db_find_key_locked(const DATABASE_HEADER *pheader, HNDLE hKey, const char *key_name, bool follow_links, HNDLE *subhKey, db_err_msg **msg)
static DATABASE * db_lock_database(HNDLE hDB, int *pstatus, const char *caller, bool check_attached=true)
INT db_find_keys(HNDLE hDB, HNDLE hKeyRoot, const char *odbpath, std::vector< HNDLE > &hKeyVector)
static int db_validate_name(const char *name, int maybe_path, const char *caller_name, db_err_msg **msg)
INT db_set_client_name(HNDLE hDB, const char *client_name)
static int db_set_value_wlocked(DATABASE *pdb, KEY *pkey_root, const char *key_name, const void *data, INT data_size, INT num_values, DWORD type, db_err_msg **msg)
INT db_set_value_index(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, const void *data, INT data_size, INT idx, DWORD type, BOOL trunc)
INT db_notify_clients_array(HNDLE hDB, HNDLE hKeys[], INT size)
INT db_open_record1(HNDLE hDB, HNDLE hKey, void *ptr, INT rec_size, WORD access_mode, void(*dispatcher)(INT, INT, void *), void *info, const char *rec_str)
INT db_merge_data(HNDLE hDB, HNDLE hKeyRoot, const char *name, void *data, INT data_size, INT num_values, INT type)
INT db_notify_clients(HNDLE hDB, HNDLE hKeyMod, int index, BOOL bWalk)
INT db_set_record(HNDLE hDB, HNDLE hKey, void *data, INT buf_size, INT align)
INT db_set_data_index1(HNDLE hDB, HNDLE hKey, const void *data, INT data_size, INT idx, DWORD type, BOOL bNotify)
static int db_parse_record(const char *rec_str, const char **out_rec_str, char *title, int title_size, char *key_name, int key_name_size, int *tid, int *n_data, int *string_length)
INT db_enum_key(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
INT EXPRT db_resize_string(HNDLE hdb, HNDLE hKeyRoot, const char *key_name, int num_values, int max_string_length)
static void db_unlock_database(DATABASE *pdb, const char *caller)
INT db_close_record(HNDLE hDB, HNDLE hKey)
static int db_validate_open_records_wlocked(DATABASE_HEADER *pheader, db_err_msg **msg)
INT db_create_record(HNDLE hDB, HNDLE hKey, const char *orig_key_name, const char *init_str)
INT db_sscanf(const char *data_str, void *data, INT *data_size, INT i, DWORD tid)
static db_err_msg * _last_error_message
static void db_msg(db_err_msg **msg, INT message_type, const char *filename, INT line, const char *routine, const char *format,...) MATTRPRINTF(6
INT db_add_open_record(HNDLE hDB, HNDLE hKey, WORD access_mode)
INT EXPRT db_set_value_string(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, const std::string *s)
INT db_set_lock_timeout(HNDLE hDB, int timeout_millisec)
static int db_enum_locked(const DATABASE_HEADER *pheader, const KEY *pkey, std::vector< HNDLE > *sub_handles, std::vector< KEY > *sub_keys, bool follow_links, db_err_msg **msg)
INT db_set_num_values(HNDLE hDB, HNDLE hKey, INT num_values)
INT db_get_record2(HNDLE hDB, HNDLE hKey, void *data, INT *xbuf_size, INT align, const char *rec_str, BOOL correct)
INT db_create_link(HNDLE hDB, HNDLE hKey, const char *link_name, const char *destination)
static void merge_records(HNDLE hDB, HNDLE hKey, KEY *pkey, INT level, void *info)
INT db_close_database(HNDLE hDB)
INT db_protect_database(HNDLE hDB)
struct db_err_msg_struct db_err_msg
const char * extract_key(const char *key_list, char *key_name, int key_name_length)
std::vector< keylist_struct > keylist_vector
static DATABASE * _database
static bool db_get_data_free_list_locked(const DATABASE_HEADER *pheader, keylist_vector *datafreelist, db_err_msg **msg)
static void json_ensure_decimal_dot(char *str)
#define RPC_DB_ADD_OPEN_RECORD
#define RPC_DB_SET_DATA_INDEX
void rpc_convert_data(void *data, INT tid, INT flags, INT total_size, INT convert_flags)
#define RPC_DB_CLOSE_DATABASE
#define RPC_DB_CREATE_RECORD
#define RPC_DB_CREATE_LINK
#define RPC_DB_NOTIFY_CLIENTS_ARRAY
#define RPC_DB_DELETE_KEY
#define RPC_DB_SET_NUM_VALUES
const char * rpc_tid_name_old(INT id)
#define RPC_DB_SET_CLIENT_NAME
#define RPC_DB_REMOVE_OPEN_RECORD
#define RPC_DB_CLOSE_ALL_DATABASES
#define RPC_DB_SET_LINK_DATA_INDEX
#define RPC_DB_RENAME_KEY
#define RPC_DB_GET_NEXT_LINK
INT rpc_call(DWORD routine_id,...)
const char * rpc_tid_name(INT id)
#define RPC_DB_SET_LINK_DATA
#define RPC_DB_GET_LINK_DATA
#define RPC_DB_SET_DATA_INDEX1
#define RPC_DB_GET_PARENT
#define RPC_DB_REORDER_KEY
#define RPC_DB_OPEN_DATABASE
#define RPC_DB_CHECK_RECORD
#define RPC_DB_GET_DATA_INDEX
int rpc_name_tid(const char *name)
#define RPC_DB_GET_KEY_INFO
bool rpc_is_mserver(void)
#define RPC_DB_FLUSH_DATABASE
#define RPC_DB_GET_KEY_TIME
#define RPC_DB_SET_RECORD
#define RPC_DB_GET_RECORD_SIZE
#define RPC_DB_GET_OPEN_RECORDS
INT rpc_get_convert_flags(void)
void rpc_convert_single(void *data, INT tid, INT flags, INT convert_flags)
#define RPC_DB_CREATE_KEY
#define RPC_DB_GET_RECORD
BOOL debug
debug printouts
std::string msprintf(const char *format,...)
#define DIR_SEPARATOR_STR
#define JSFLAG_FOLLOW_LINKS
#define MATTRPRINTF(a, b)
#define JSFLAG_OMIT_LAST_WRITTEN
unsigned long long UINT64
#define JSFLAG_OMIT_NAMES
#define WATCHDOG_INTERVAL
#define JS_MUST_BE_SUBDIR
#define message(type, str)
#define write(n, a, f, d)
struct callback_addr callback
BOOL match(char *pat, char *str)
OPEN_RECORD open_record[MAX_OPEN_RECORDS]
DATABASE_CLIENT client[MAX_CLIENTS]
DATABASE_HEADER * database_header
NET_COMMAND_HEADER header
void(* dispatcher)(INT, INT, void *)
DATABASE_HEADER * pheader
void(* dispatcher)(INT, INT, INT, void *info)
static double comma(double a, double b)
static te_expr * list(state *s)