MIDAS
ODB Functions (db_xxx)

Classes

struct  db_err_msg_struct
 
struct  print_key_info_buf
 
struct  UPDATE_OPEN_RECORDS
 

Macros

#define CHECK_OPEN_RECORD   1
 
#define HAVE_DB_GET_VALUE_STRING_CREATE_STRING_LENGTH   1
 

Typedefs

typedef struct db_err_msg_struct db_err_msg
 

Functions

INT db_save_xml_key (HNDLE hDB, HNDLE hKey, INT level, MXML_WRITER *writer)
 
static void db_msg (db_err_msg **msg, INT message_type, const char *filename, INT line, const char *routine, const char *format,...) MATTRPRINTF(6
 
static void static void db_print_msg (const 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, HNDLE *subhKey, db_err_msg **msg)
 
static const KEYdb_find_pkey_locked (const DATABASE_HEADER *pheader, const KEY *pkey, const char *key_name, int *pstatus, db_err_msg **msg)
 
static std::string db_get_path_locked (const DATABASE_HEADER *pheader, HNDLE hKey)
 
static std::string db_get_path_locked (const DATABASE_HEADER *pheader, const KEY *pkey)
 
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)
 
static int db_set_mode_wlocked (DATABASE_HEADER *, KEY *, WORD mode, int recurse, db_err_msg **)
 
static const KEYdb_resolve_link_locked (const DATABASE_HEADER *, const KEY *, int *pstatus, db_err_msg **)
 
static int db_notify_clients_locked (const DATABASE_HEADER *pheader, HNDLE hDB, HNDLE hKeyMod, int index, BOOL bWalk, db_err_msg **msg)
 
static int db_create_key_wlocked (DATABASE_HEADER *pheader, KEY *parentKey, const char *key_name, DWORD type, KEY **pnewkey, db_err_msg **msg)
 
static int db_set_value_wlocked (DATABASE_HEADER *pheader, HNDLE hDB, KEY *pkey_root, const char *key_name, const void *data, INT data_size, INT num_values, DWORD type, 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)
 
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)
 
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)
 
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)
 
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_remove_open_record_wlocked (DATABASE *pdb, DATABASE_HEADER *pheader, HNDLE hKey)
 
static bool db_validate_key_offset (const DATABASE_HEADER *pheader, int offset)
 
static void * malloc_key (DATABASE_HEADER *pheader, INT size, const char *caller)
 
static void free_key (DATABASE_HEADER *pheader, void *address, INT size)
 
static int validate_free_data (DATABASE_HEADER *pheader, int free_data)
 
static void * malloc_data (DATABASE_HEADER *pheader, INT size)
 
static int free_data (DATABASE_HEADER *pheader, void *address, INT size, const char *caller)
 
static void * realloc_data (DATABASE_HEADER *pheader, void *address, INT old_size, INT new_size, const char *caller)
 
char * strcomb (const char **list)
 
std::string strcomb1 (const char **list)
 
static void add_to_buf (struct print_key_info_buf *buf, const char *s)
 
static INT print_key_info (HNDLE hDB, HNDLE hKey, KEY *pkey, INT level, void *info)
 
static bool db_validate_data_offset (const DATABASE_HEADER *pheader, int offset)
 
INT db_show_mem (HNDLE hDB, char **result, BOOL verbose)
 
INT db_get_free_mem (HNDLE hDB, INT *key_size, INT *data_size)
 
static bool is_utf8 (const char *string)
 
static int db_validate_name (const char *name, int maybe_path, const char *caller_name, db_err_msg **msg)
 
static bool db_validate_hkey (const DATABASE_HEADER *pheader, HNDLE hKey)
 
static const KEYdb_get_pkey (const DATABASE_HEADER *pheader, HNDLE hKey, int *pstatus, const char *caller, db_err_msg **msg)
 
static const KEYLISTdb_get_pkeylist (const DATABASE_HEADER *pheader, HNDLE hKey, const KEY *pkey, const char *caller, db_err_msg **msg, bool kludge_repair=false)
 
static HNDLE db_pkey_to_hkey (const DATABASE_HEADER *pheader, const KEY *pkey)
 
static const KEYdb_get_parent (const DATABASE_HEADER *pheader, const KEY *pkey, int *pstatus, const char *caller, db_err_msg **msg)
 
static const KEYdb_enum_first_locked (const DATABASE_HEADER *pheader, const KEY *pkey, db_err_msg **msg)
 
static const KEYdb_enum_next_locked (const DATABASE_HEADER *pheader, const KEY *pdir, const KEY *pkey, db_err_msg **msg)
 
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)
 
DATABASE_CLIENTdb_get_my_client_locked (DATABASE *pdb)
 
static void db_validate_sizes ()
 
static int db_update_open_record_wlocked (const DATABASE_HEADER *xpheader, const KEY *xpkey, int level, void *voidp, db_err_msg **msg)
 
static int db_validate_open_records_wlocked (DATABASE_HEADER *pheader, db_err_msg **msg)
 
static bool db_validate_and_repair_db_wlocked (DATABASE_HEADER *pheader, db_err_msg **msg)
 
INT db_open_database (const char *xdatabase_name, INT database_size, HNDLE *hDB, const char *client_name)
 
INT db_close_database (HNDLE hDB)
 
INT db_flush_database (HNDLE hDB)
 
INT db_close_all_databases (void)
 
INT db_set_client_name (HNDLE hDB, const char *client_name)
 
INT db_lock_database (HNDLE hDB)
 
INT db_allow_write_locked (DATABASE *p, const char *caller_name)
 
INT db_unlock_database (HNDLE hDB)
 
INT db_set_lock_timeout (HNDLE hDB, int timeout_millisec)
 
INT db_update_last_activity (DWORD millitime)
 
static void db_delete_client_wlocked (DATABASE_HEADER *pheader, int jclient, db_err_msg **msg)
 
static int db_delete_client_info_wlocked (HNDLE hDB, DATABASE_HEADER *pheader, int pid, db_err_msg **msg)
 
int db_delete_client_info (HNDLE hDB, int pid)
 
void db_cleanup (const char *who, DWORD actual_time, BOOL wrong_interval)
 
void db_cleanup2 (const char *client_name, int ignore_timeout, DWORD actual_time, const char *who)
 
void db_set_watchdog_params (DWORD timeout)
 
INT db_get_watchdog_info (HNDLE hDB, const char *client_name, DWORD *timeout, DWORD *last)
 
INT db_check_client (HNDLE hDB, HNDLE hKeyClient)
 
INT db_protect_database (HNDLE hDB)
 
const char * extract_key (const char *key_list, char *key_name, int key_name_length)
 
BOOL equal_ustring (const char *str1, const char *str2)
 
BOOL ends_with_ustring (const char *str, const char *suffix)
 
BOOL strmatch (char *pattern, char *str)
 
void strarrayindex (char *odbpath, int *index1, int *index2)
 
INT db_create_key (HNDLE hDB, HNDLE hKey, const char *key_name, DWORD type)
 
INT db_create_link (HNDLE hDB, HNDLE hKey, const char *link_name, const char *destination)
 
INT db_delete_key1 (HNDLE hDB, HNDLE hKey, INT level, BOOL follow_links)
 
INT db_delete_key (HNDLE hDB, HNDLE hKey, BOOL follow_links)
 
INT db_find_key (HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
 
INT db_find_key1 (HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
 
INT db_find_link (HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
 
INT db_find_link1 (HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
 
INT db_find_keys (HNDLE hDB, HNDLE hKeyRoot, char *odbpath, std::vector< HNDLE > &hKeyVector)
 
INT db_get_parent (HNDLE hDB, HNDLE hKey, HNDLE *parenthKey)
 
INT db_scan_tree (HNDLE hDB, HNDLE hKey, INT level, INT(*callback)(HNDLE, HNDLE, KEY *, INT, void *), void *info)
 
int db_scan_tree_locked (const DATABASE_HEADER *pheader, const KEY *pkey, int level, int(*callback)(const DATABASE_HEADER *pheader, const KEY *, int, void *, db_err_msg **msg), void *info, db_err_msg **msg)
 
INT db_scan_tree_link (HNDLE hDB, HNDLE hKey, INT level, void(*callback)(HNDLE, HNDLE, KEY *, INT, void *), void *info)
 
INT db_get_path (HNDLE hDB, HNDLE hKey, char *path, INT buf_size)
 
std::string db_get_path (HNDLE hDB, HNDLE hKey)
 
static int db_find_open_records (HNDLE hDB, HNDLE hKey, KEY *key, INT level, void *xresult)
 
static int db_fix_open_records (HNDLE hDB, HNDLE hKey, KEY *key, INT level, void *xresult)
 
INT db_get_open_records (HNDLE hDB, HNDLE hKey, char *str, INT buf_size, BOOL fix)
 
INT db_set_value (HNDLE hDB, HNDLE hKeyRoot, const char *key_name, const void *data, INT data_size, INT num_values, DWORD type)
 
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_get_value (HNDLE hDB, HNDLE hKeyRoot, const char *key_name, void *data, INT *buf_size, DWORD type, BOOL create)
 
INT db_enum_key (HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
 
INT db_enum_link (HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
 
INT db_get_next_link (HNDLE hDB, HNDLE hKey, HNDLE *subkey_handle)
 
static INT db_get_key_locked (const DATABASE_HEADER *pheader, HNDLE hKey, KEY *key, db_err_msg **msg)
 
INT db_get_key (HNDLE hDB, HNDLE hKey, KEY *key)
 
INT db_get_link (HNDLE hDB, HNDLE hKey, KEY *key)
 
INT db_get_key_time (HNDLE hDB, HNDLE hKey, DWORD *delta)
 
INT db_get_key_info (HNDLE hDB, HNDLE hKey, char *name, INT name_size, INT *type, INT *num_values, INT *item_size)
 
INT db_rename_key (HNDLE hDB, HNDLE hKey, const char *name)
 
INT db_reorder_key (HNDLE hDB, HNDLE hKey, INT idx)
 
INT db_get_data (HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, DWORD type)
 
INT db_get_link_data (HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, DWORD type)
 
INT db_get_data1 (HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, DWORD type, INT *num_values)
 
INT db_get_data_index (HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT idx, DWORD type)
 
INT db_set_data (HNDLE hDB, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type)
 
INT db_set_data1 (HNDLE hDB, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type)
 
INT db_set_link_data (HNDLE hDB, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type)
 
INT db_set_num_values (HNDLE hDB, HNDLE hKey, INT num_values)
 
INT db_set_data_index (HNDLE hDB, HNDLE hKey, const void *data, INT data_size, INT idx, DWORD type)
 
INT db_set_link_data_index (HNDLE hDB, HNDLE hKey, const void *data, INT data_size, INT idx, DWORD type)
 
INT db_set_data_index1 (HNDLE hDB, HNDLE hKey, const void *data, INT data_size, INT idx, DWORD type, BOOL bNotify)
 
INT db_merge_data (HNDLE hDB, HNDLE hKeyRoot, const char *name, void *data, INT data_size, INT num_values, INT type)
 
INT db_set_mode (HNDLE hDB, HNDLE hKey, WORD mode, BOOL recurse)
 
INT db_load (HNDLE hDB, HNDLE hKeyRoot, const char *filename, BOOL bRemote)
 
INT db_copy (HNDLE hDB, HNDLE hKey, char *buffer, INT *buffer_size, const char *path)
 
INT db_paste (HNDLE hDB, HNDLE hKeyRoot, const char *buffer)
 
static int db_paste_node (HNDLE hDB, HNDLE hKeyRoot, PMXML_NODE node)
 
INT db_paste_xml (HNDLE hDB, HNDLE hKeyRoot, const char *buffer)
 
INT db_copy_xml (HNDLE hDB, HNDLE hKey, char *buffer, int *buffer_size, bool header)
 
void name2c (char *str)
 
static void db_save_tree_struct (HNDLE hDB, HNDLE hKey, int hfile, INT level)
 
INT db_save (HNDLE hDB, HNDLE hKey, const char *filename, BOOL bRemote)
 
void xml_encode (char *src, int size)
 
INT db_save_xml (HNDLE hDB, HNDLE hKey, const char *filename)
 
void json_write (char **buffer, int *buffer_size, int *buffer_end, int level, const char *s, int quoted)
 
static void json_ensure_decimal_dot (char *str)
 
static void json_write_data (char **buffer, int *buffer_size, int *buffer_end, int level, const KEY *key, const char *p)
 
static void json_write_key (HNDLE hDB, HNDLE hKey, const KEY *key, const char *link_path, char **buffer, int *buffer_size, int *buffer_end)
 
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_copy_json_array (HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end)
 
INT db_copy_json_index (HNDLE hDB, HNDLE hKey, int index, char **buffer, int *buffer_size, int *buffer_end)
 
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)
 
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 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)
 
INT db_copy_json_ls (HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end)
 
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_copy_json_save (HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end)
 
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_save_json (HNDLE hDB, HNDLE hKey, const char *filename, int flags)
 
INT db_save_struct (HNDLE hDB, HNDLE hKey, const char *file_name, const char *struct_name, BOOL append)
 
INT db_save_string (HNDLE hDB, HNDLE hKey, const char *file_name, const char *string_name, BOOL append)
 
INT db_sprintf (char *string, const void *data, INT data_size, INT idx, DWORD type)
 
INT db_sprintff (char *string, const char *format, const void *data, INT data_size, INT idx, DWORD type)
 
INT db_sprintfh (char *string, const void *data, INT data_size, INT idx, DWORD type)
 
std::string db_sprintf (const void *data, INT data_size, INT idx, DWORD type)
 
std::string db_sprintff (const char *format, const void *data, INT data_size, INT idx, DWORD type)
 
std::string db_sprintfh (const void *data, INT data_size, INT idx, DWORD type)
 
INT db_sscanf (const char *data_str, void *data, INT *data_size, INT i, DWORD tid)
 
static void db_recurse_record_tree_locked (HNDLE hDB, const DATABASE_HEADER *pheader, const KEY *pkey, void **data, INT *total_size, INT base_align, INT *max_align, BOOL bSet, INT convert_flags, db_err_msg **msg)
 
static void db_recurse_record_tree_locked (HNDLE hDB, HNDLE hKey, void **data, INT *total_size, INT base_align, INT *max_align, BOOL bSet, INT convert_flags, db_err_msg **msg)
 
INT db_get_record_size (HNDLE hDB, HNDLE hKey, INT align, INT *buf_size)
 
INT db_get_record (HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT align)
 
INT db_get_record1 (HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT align, const char *rec_str)
 
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)
 
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_get_record2 (HNDLE hDB, HNDLE hKey, void *data, INT *xbuf_size, INT align, const char *rec_str, BOOL correct)
 
INT db_set_record (HNDLE hDB, HNDLE hKey, void *data, INT buf_size, INT align)
 
INT db_add_open_record (HNDLE hDB, HNDLE hKey, WORD access_mode)
 
INT db_remove_open_record (HNDLE hDB, HNDLE hKey, BOOL lock)
 
INT db_notify_clients (HNDLE hDB, HNDLE hKeyMod, int index, BOOL bWalk)
 
INT db_notify_clients_array (HNDLE hDB, HNDLE hKeys[], INT size)
 
static void merge_records (HNDLE hDB, HNDLE hKey, KEY *pkey, INT level, void *info)
 
static void check_open_keys (HNDLE hDB, HNDLE hKey, KEY *pkey, INT level, void *info)
 
INT db_create_record (HNDLE hDB, HNDLE hKey, const char *orig_key_name, const char *init_str)
 
INT db_check_record (HNDLE hDB, HNDLE hKey, const char *keyname, const char *rec_str, BOOL correct)
 
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_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_close_record (HNDLE hDB, HNDLE hKey)
 
INT db_close_all_records ()
 
INT db_update_record_local (INT hDB, INT hKeyRoot, INT hKey, int index)
 
INT db_update_record_mserver (INT hDB, INT hKeyRoot, INT hKey, int index, int client_socket)
 
INT db_send_changed_records ()
 
INT db_watch (HNDLE hDB, HNDLE hKey, void(*dispatcher)(INT, INT, INT, void *), void *info)
 
INT db_unwatch (HNDLE hDB, HNDLE hKey)
 
INT db_unwatch_all ()
 
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 EXPRT db_set_value_string (HNDLE hDB, HNDLE hKeyRoot, const char *key_name, const std::string *s)
 
INT EXPRT db_resize_string (HNDLE hdb, HNDLE hKeyRoot, const char *key_name, int num_values, int max_string_length)
 
MJsonNode * db_scl (HNDLE hDB)
 
MJsonNode * db_sor (HNDLE hDB, const char *root_path)
 
INT EXPRT db_set_record2 (HNDLE hdb, HNDLE hKey, void *data, INT buf_size, INT align, const char *rec_str)
 
INT EXPRT db_watch (HNDLE hDB, HNDLE hKey, void(*dispatcher)(INT, INT, INT, void *info), void *info)
 
INT EXPRT db_load_json (HNDLE hdb, HNDLE key_handle, const char *filename)
 
INT EXPRT db_paste_json (HNDLE hDB, HNDLE hKey, const char *buffer)
 
INT EXPRT db_paste_json_node (HNDLE hDB, HNDLE hKey, int index, const MJsonNode *json_node)
 

Variables

static DATABASE_database
 
static INT _database_entries = 0
 
static RECORD_LIST_record_list
 
static INT _record_list_entries = 0
 
static WATCH_LIST_watch_list
 
static INT _watch_list_entries = 0
 
static db_err_msg_last_error_message = NULL
 
static int _global_open_count
 

Detailed Description

dox


Macro Definition Documentation

◆ CHECK_OPEN_RECORD

#define CHECK_OPEN_RECORD   1

dox

Definition at line 44 of file odb.cxx.

◆ HAVE_DB_GET_VALUE_STRING_CREATE_STRING_LENGTH

#define HAVE_DB_GET_VALUE_STRING_CREATE_STRING_LENGTH   1

Definition at line 1889 of file midas.h.

Typedef Documentation

◆ db_err_msg

typedef struct db_err_msg_struct db_err_msg

Definition at line 67 of file odb.cxx.

Function Documentation

◆ add_to_buf()

static void add_to_buf ( struct print_key_info_buf buf,
const char *  s 
)
static

Definition at line 623 of file odb.cxx.

624 {
625  int len = strlen(s);
626  if (buf->used + len + 10 > buf->alloc_size) {
627  int new_size = 1024 + 2*buf->alloc_size + len;
628  //printf("realloc %d->%d, used %d, adding %d\n", buf->alloc_size, new_size, buf->used, len);
629  buf->buf = (char*)realloc(buf->buf, new_size);
630  assert(buf->buf != NULL);
631  buf->alloc_size = new_size;
632  }
633 
634  memcpy(buf->buf + buf->used, s, len);
635  buf->used += len;
636  buf->buf[buf->used] = 0; // zero-terminate the string
637 }
Here is the caller graph for this function:

◆ check_open_keys()

static void check_open_keys ( HNDLE  hDB,
HNDLE  hKey,
KEY pkey,
INT  level,
void *  info 
)
static

Definition at line 12737 of file odb.cxx.

12738 {
12739  if (pkey->notify_count)
12741 }
static int _global_open_count
Definition: odb.cxx:12735
WORD notify_count
Definition: midas.h:1040
Here is the caller graph for this function:

◆ db_add_open_record()

INT EXPRT db_add_open_record ( HNDLE  hDB,
HNDLE  hKey,
WORD  access_mode 
)

dox

Definition at line 12367 of file odb.cxx.

12375 {
12376  if (rpc_is_remote())
12377  return rpc_call(RPC_DB_ADD_OPEN_RECORD, hDB, hKey, access_mode);
12378 
12379 #ifdef LOCAL_ROUTINES
12380  {
12381  INT i;
12382  int status;
12383 
12384  if (hDB > _database_entries || hDB <= 0) {
12385  cm_msg(MERROR, "db_add_open_record", "invalid database handle");
12386  return DB_INVALID_HANDLE;
12387  }
12388 
12389  db_err_msg* msg = NULL;
12390 
12391  /* lock database */
12393 
12394  DATABASE *pdb = &_database[hDB - 1];
12395  DATABASE_HEADER *pheader = pdb->database_header;
12396  DATABASE_CLIENT *pclient = db_get_my_client_locked(pdb);
12397 
12398  /* check if key is already open */
12399  for (i = 0; i < pclient->max_index; i++) {
12400  if (pclient->open_record[i].handle == hKey)
12401  break;
12402  }
12403 
12404  if (i < pclient->max_index) {
12406  return DB_SUCCESS;
12407  }
12408 
12409  /* not found, search free entry */
12410  for (i = 0; i < pclient->max_index; i++) {
12411  if (pclient->open_record[i].handle == 0)
12412  break;
12413  }
12414 
12415  /* check if maximum number reached */
12416  if (i == MAX_OPEN_RECORDS) {
12418  return DB_NO_MEMORY;
12419  }
12420 
12421  db_allow_write_locked(pdb, "db_add_open_record");
12422 
12423  KEY *pkey = (KEY*)db_get_pkey(pheader, hKey, &status, "db_add_open_record", &msg);
12424 
12425  if (!pkey) {
12427  if (msg)
12428  db_flush_msg(&msg);
12429  return status;
12430  }
12431 
12432  if (i == pclient->max_index)
12433  pclient->max_index++;
12434 
12435  pclient->open_record[i].handle = hKey;
12436  pclient->open_record[i].access_mode = access_mode;
12437 
12438  /* increment notify_count */
12439  pkey->notify_count++;
12440 
12441  pclient->num_open_records++;
12442 
12443  /* set exclusive bit if requested */
12444  if (access_mode & MODE_WRITE)
12445  db_set_mode(hDB, hKey, (WORD) (pkey->access_mode | MODE_EXCLUSIVE), 2);
12446 
12448  }
12449 #endif /* LOCAL_ROUTINES */
12450 
12451  return DB_SUCCESS;
12452 }
#define DB_INVALID_HANDLE
Definition: midas.h:641
#define DB_SUCCESS
Definition: midas.h:637
#define DB_NO_MEMORY
Definition: midas.h:639
unsigned short int WORD
Definition: mcstd.h:49
#define MODE_EXCLUSIVE
Definition: midas.h:380
#define MODE_WRITE
Definition: midas.h:378
#define MERROR
Definition: midas.h:565
INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
Definition: midas.cxx:917
INT db_lock_database(HNDLE hDB)
Definition: odb.cxx:2446
INT db_unlock_database(HNDLE hDB)
Definition: odb.cxx:2565
INT db_set_mode(HNDLE hDB, HNDLE hKey, WORD mode, BOOL recurse)
Definition: odb.cxx:8021
INT db_allow_write_locked(DATABASE *p, const char *caller_name)
Definition: odb.cxx:2537
DATABASE_CLIENT * db_get_my_client_locked(DATABASE *pdb)
Definition: odb.cxx:1368
static INT _database_entries
Definition: odb.cxx:58
static void db_flush_msg(db_err_msg **msg)
Definition: odb.cxx:170
static const KEY * db_get_pkey(const DATABASE_HEADER *pheader, HNDLE hKey, int *pstatus, const char *caller, db_err_msg **msg)
Definition: odb.cxx:933
static DATABASE * _database
Definition: odb.cxx:57
#define RPC_DB_ADD_OPEN_RECORD
Definition: mrpc.h:72
bool rpc_is_remote(void)
Definition: midas.cxx:12728
INT rpc_call(DWORD routine_id,...)
Definition: midas.cxx:13630
HNDLE hKey
Definition: lazylogger.cxx:207
HNDLE hDB
main ODB handle
Definition: mana.cxx:207
INT i
Definition: mdump.cxx:35
int INT
Definition: midas.h:129
#define MAX_OPEN_RECORDS
Definition: midas.h:283
DWORD status
Definition: odbhist.cxx:39
OPEN_RECORD open_record[MAX_OPEN_RECORDS]
Definition: msystem.h:421
INT num_open_records
Definition: msystem.h:416
DATABASE_HEADER * database_header
Definition: msystem.h:446
Definition: midas.h:1032
WORD access_mode
Definition: midas.h:1039
WORD access_mode
Definition: msystem.h:405
INT handle
Definition: msystem.h:404
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_allow_write_locked()

INT db_allow_write_locked ( DATABASE p,
const char *  caller_name 
)

Definition at line 2537 of file odb.cxx.

2538 {
2539  assert(p);
2540  if (p->protect && !p->protect_write) {
2541  int status;
2542  assert(p->lock_cnt > 0);
2543  assert(p->database_header != NULL);
2544  assert(p->protect_read);
2545  status = ss_shm_unprotect(p->shm_handle, &p->shm_adr, p->shm_size, TRUE, TRUE, caller_name);
2546  if (status != SS_SUCCESS) {
2547  cm_msg(MERROR, "db_allow_write_locked", "cannot write to ODB, ss_shm_unprotect(TRUE,TRUE) failed with status %d, aborting...", status);
2549  abort();
2550  }
2552  p->protect_read = TRUE;
2553  p->protect_write = TRUE;
2554  }
2555  return DB_SUCCESS;
2556 }
#define SS_SUCCESS
Definition: midas.h:669
INT ss_shm_unprotect(HNDLE handle, void **adr, size_t shm_size, BOOL read, BOOL write, const char *caller_name)
Definition: system.cxx:1066
INT cm_msg_flush_buffer()
Definition: midas.cxx:867
#define TRUE
Definition: midas.h:182
BOOL protect
Definition: msystem.h:453
HNDLE shm_size
Definition: msystem.h:451
BOOL protect_read
Definition: msystem.h:454
INT lock_cnt
Definition: msystem.h:449
HNDLE shm_handle
Definition: msystem.h:452
BOOL protect_write
Definition: msystem.h:455
void * shm_adr
Definition: msystem.h:450
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_check_client()

INT db_check_client ( HNDLE  hDB,
HNDLE  hKeyClient 
)

Check if a client with a /system/client/xxx entry has a valid entry in the ODB client table. If not, remove that client from the /system/client tree.

Parameters
hDBHandle to online database
hKeyClientHandle to client key
Returns
CM_SUCCESS, CM_NO_CLIENT

Definition at line 3049 of file odb.cxx.

3050 {
3051  if (hDB > _database_entries || hDB <= 0) {
3052  cm_msg(MERROR, "db_check_client", "invalid database handle");
3053  return DB_INVALID_HANDLE;
3054  }
3055 
3056  if (!_database[hDB - 1].attached) {
3057  cm_msg(MERROR, "db_check_client", "invalid database handle");
3058  return DB_INVALID_HANDLE;
3059  }
3060 
3061  int status;
3062 
3064 
3065  db_err_msg* msg = NULL;
3066 
3067  DATABASE *pdb = &_database[hDB - 1];
3068  DATABASE_HEADER *pheader = pdb->database_header;
3069 
3070  const KEY* pkey = db_get_pkey(pheader, hKeyClient, &status, "db_check_client", &msg);
3071 
3072  if (!pkey) {
3074  if (msg)
3075  db_flush_msg(&msg);
3076  return CM_NO_CLIENT;
3077  }
3078 
3079  int client_pid = atoi(pkey->name);
3080 
3081  const KEY* pkey_name = db_find_pkey_locked(pheader, pkey, "Name", &status, &msg);
3082 
3083  if (!pkey_name) {
3085  if (msg)
3086  db_flush_msg(&msg);
3087  return CM_NO_CLIENT;
3088  }
3089 
3090  char name[256];
3091  name[0] = 0;
3092  int size = sizeof(name);
3093  status = db_get_data_locked(pheader, pkey_name, 0, name, &size, TID_STRING, &msg);
3094 
3095  //fprintf(stderr, "db_check_client: hkey %d, status %d, pid %d, name \'%s\'\n", hKeyClient, status, client_pid, name);
3096 
3097  if (status != DB_SUCCESS) {
3099  if (msg)
3100  db_flush_msg(&msg);
3101  return CM_NO_CLIENT;
3102  }
3103 
3104  bool dead = false;
3105  bool found = false;
3106 
3107  /* loop through clients */
3108  for (int i = 0; i < pheader->max_client_index; i++) {
3109  DATABASE_CLIENT *pclient = &pheader->client[i];
3110  if (pclient->pid == client_pid) {
3111  found = true;
3112  break;
3113  }
3114  }
3115 
3116  if (found) {
3117  /* check that the client is still running: PID still exists */
3118  if (!ss_pid_exists(client_pid)) {
3119  dead = true;
3120  }
3121  }
3122 
3123  status = DB_SUCCESS;
3124 
3125  if (!found || dead) {
3126  /* client not found : delete ODB stucture */
3127 
3128  db_allow_write_locked(pdb, "db_check_client");
3129 
3130  status = db_delete_client_info_wlocked(hDB, pheader, client_pid, &msg);
3131 
3132  if (status != DB_SUCCESS)
3133  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);
3134  else if (!found)
3135  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);
3136  else if (dead)
3137  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);
3138 
3139  status = CM_NO_CLIENT;
3140  }
3141 
3143  if (msg)
3144  db_flush_msg(&msg);
3145 
3146  return status;
3147 }
#define CM_NO_CLIENT
Definition: midas.h:590
#define MINFO
Definition: midas.h:566
#define TID_STRING
Definition: midas.h:353
BOOL ss_pid_exists(int pid)
Definition: system.cxx:1446
static int db_delete_client_info_wlocked(HNDLE hDB, DATABASE_HEADER *pheader, int pid, db_err_msg **msg)
Definition: odb.cxx:2750
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)
Definition: odb.cxx:5496
static const KEY * db_find_pkey_locked(const DATABASE_HEADER *pheader, const KEY *pkey, const char *key_name, int *pstatus, db_err_msg **msg)
Definition: odb.cxx:3855
static void db_msg(db_err_msg **msg, INT message_type, const char *filename, INT line, const char *routine, const char *format,...) MATTRPRINTF(6
Definition: odb.cxx:124
#define name(x)
Definition: midas_macro.h:24
DATABASE_CLIENT client[MAX_CLIENTS]
Definition: msystem.h:436
INT max_client_index
Definition: msystem.h:429
char name[NAME_LENGTH]
Definition: midas.h:1035
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_check_record()

INT EXPRT db_check_record ( HNDLE  hDB,
HNDLE  hKey,
const char *  keyname,
const char *  rec_str,
BOOL  correct 
)

This function ensures that a certain ODB subtree matches a given C structure, by comparing the init_str with the current ODB structure. If the record does not exist at all, it is created with the default values in init_str. If it does exist but does not match the variables in init_str, the function returns an error if correct=FALSE or calls db_create_record() if correct=TRUE.

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
keynameName of key to search, can contain directories.
rec_strASCII representation of ODB record in the format
correctIf TRUE, correct ODB record if necessary
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_NO_KEY, DB_STRUCT_MISMATCH

Definition at line 12975 of file odb.cxx.

12976 {
12977  char line[MAX_STRING_LENGTH];
12978  char title[MAX_STRING_LENGTH];
12979  char key_name[MAX_STRING_LENGTH];
12980  char info_str[MAX_STRING_LENGTH + 50];
12981  char *pc;
12982  const char *pold, *rec_str_orig;
12983  DWORD tid;
12984  INT i, j, n_data, string_length, status;
12985  HNDLE hKeyRoot, hKeyTest;
12986  KEY key;
12987  int bad_string_length;
12988 
12989  if (rpc_is_remote())
12990  return rpc_call(RPC_DB_CHECK_RECORD, hDB, hKey, keyname, rec_str, correct);
12991 
12992  /* check if record exists */
12993  status = db_find_key(hDB, hKey, keyname, &hKeyRoot);
12994 
12995  /* create record if not */
12996  if (status == DB_NO_KEY) {
12997  if (correct)
12998  return db_create_record(hDB, hKey, keyname, rec_str);
12999  return DB_NO_KEY;
13000  }
13001 
13002  assert(hKeyRoot);
13003 
13004  title[0] = 0;
13005  rec_str_orig = rec_str;
13006 
13007  db_get_key(hDB, hKeyRoot, &key);
13008  if (key.type == TID_KEY)
13009  /* get next subkey which is not of type TID_KEY */
13010  db_get_next_link(hDB, hKeyRoot, &hKeyTest);
13011  else
13012  /* test root key itself */
13013  hKeyTest = hKeyRoot;
13014 
13015  if (hKeyTest == 0 && *rec_str != 0) {
13016  if (correct)
13017  return db_create_record(hDB, hKey, keyname, rec_str_orig);
13018 
13019  return DB_STRUCT_MISMATCH;
13020  }
13021 
13022  do {
13023  if (*rec_str == 0)
13024  break;
13025 
13026  for (i = 0; *rec_str != '\n' && *rec_str && i < MAX_STRING_LENGTH; i++)
13027  line[i] = *rec_str++;
13028 
13029  if (i == MAX_STRING_LENGTH) {
13030  cm_msg(MERROR, "db_check_record", "line too long");
13031  return DB_TRUNCATED;
13032  }
13033 
13034  line[i] = 0;
13035  if (*rec_str == '\n')
13036  rec_str++;
13037 
13038  /* check if it is a section title */
13039  if (line[0] == '[') {
13040  /* extract title and append '/' */
13041  strcpy(title, line + 1);
13042  if (strchr(title, ']'))
13043  *strchr(title, ']') = 0;
13044  if (title[0] && title[strlen(title) - 1] != '/')
13045  strcat(title, "/");
13046  } else {
13047  /* valid data line if it includes '=' and no ';' */
13048  if (strchr(line, '=') && line[0] != ';') {
13049  /* copy type info and data */
13050  pc = strchr(line, '=') + 1;
13051  while (*pc == ' ')
13052  pc++;
13053  strcpy(info_str, pc);
13054 
13055  /* extract key name */
13056  *strchr(line, '=') = 0;
13057 
13058  pc = &line[strlen(line) - 1];
13059  while (*pc == ' ')
13060  *pc-- = 0;
13061 
13062  strlcpy(key_name, line, sizeof(key_name));
13063 
13064  /* evaluate type info */
13065  strcpy(line, info_str);
13066  if (strchr(line, ' '))
13067  *strchr(line, ' ') = 0;
13068 
13069  n_data = 1;
13070  if (strchr(line, '[')) {
13071  n_data = atol(strchr(line, '[') + 1);
13072  *strchr(line, '[') = 0;
13073  }
13074 
13075  for (tid = 0; tid < TID_LAST; tid++)
13076  if (strcmp(rpc_tid_name(tid), line) == 0)
13077  break;
13078  if (tid == TID_LAST) {
13079  for (tid = 0; tid < TID_LAST; tid++)
13080  if (strcmp(rpc_tid_name_old(tid), line) == 0)
13081  break;
13082  }
13083 
13084  string_length = 0;
13085 
13086  if (tid == TID_LAST)
13087  cm_msg(MERROR, "db_check_record", "found unknown data type \"%s\" in ODB file", line);
13088  else {
13089  /* skip type info */
13090  pc = info_str;
13091  while (*pc != ' ' && *pc)
13092  pc++;
13093  while ((*pc == ' ' || *pc == ':') && *pc)
13094  pc++;
13095 
13096  if (n_data > 1) {
13097  info_str[0] = 0;
13098  if (!*rec_str)
13099  break;
13100 
13101  for (j = 0; *rec_str != '\n' && *rec_str; j++)
13102  info_str[j] = *rec_str++;
13103  info_str[j] = 0;
13104  if (*rec_str == '\n')
13105  rec_str++;
13106  }
13107 
13108  for (i = 0; i < n_data; i++) {
13109  /* strip trailing \n */
13110  pc = &info_str[strlen(info_str) - 1];
13111  while (*pc == '\n' || *pc == '\r')
13112  *pc-- = 0;
13113 
13114  if (tid == TID_STRING || tid == TID_LINK) {
13115  if (!string_length) {
13116  if (info_str[1] == '=')
13117  string_length = -1;
13118  else {
13119  pc = strchr(info_str, '[');
13120  if (pc != NULL)
13121  string_length = atoi(pc + 1);
13122  else
13123  string_length = -1;
13124  }
13125  if (string_length > MAX_STRING_LENGTH) {
13126  string_length = MAX_STRING_LENGTH;
13127  cm_msg(MERROR, "db_check_record", "found string exceeding MAX_STRING_LENGTH");
13128  }
13129  }
13130 
13131  if (string_length == -1) {
13132  /* multi-line string */
13133  if (strstr(rec_str, "\n====#$@$#====\n") != NULL) {
13134  string_length = (POINTER_T) strstr(rec_str, "\n====#$@$#====\n") - (POINTER_T) rec_str + 1;
13135 
13136  rec_str = strstr(rec_str, "\n====#$@$#====\n") + strlen("\n====#$@$#====\n");
13137  } else
13138  cm_msg(MERROR, "db_check_record", "found multi-line string without termination sequence");
13139  } else {
13140  if (strchr(info_str, ']'))
13141  pc = strchr(info_str, ']') + 1;
13142  else
13143  pc = info_str + 2;
13144  while (*pc && *pc != ' ')
13145  pc++;
13146  while (*pc && *pc == ' ')
13147  pc++;
13148 
13149  /* limit string size */
13150  *(pc + string_length - 1) = 0;
13151  }
13152  } else {
13153  pc = info_str;
13154 
13155  if (n_data > 1 && info_str[0] == '[') {
13156  pc = strchr(info_str, ']') + 1;
13157  while (*pc && *pc == ' ')
13158  pc++;
13159  }
13160  }
13161 
13162  if (i < n_data - 1) {
13163  info_str[0] = 0;
13164  if (!*rec_str)
13165  break;
13166 
13167  pold = rec_str;
13168 
13169  for (j = 0; *rec_str != '\n' && *rec_str; j++)
13170  info_str[j] = *rec_str++;
13171  info_str[j] = 0;
13172  if (*rec_str == '\n')
13173  rec_str++;
13174 
13175  /* test if valid data */
13176  if (tid != TID_STRING && tid != TID_LINK) {
13177  if (info_str[0] == 0 || (strchr(info_str, '=')
13178  && strchr(info_str, ':')))
13179  rec_str = pold;
13180  }
13181  }
13182  }
13183 
13184  /* if rec_str contains key, but not ODB, return mismatch */
13185  if (!hKeyTest) {
13186  if (correct)
13187  return db_create_record(hDB, hKey, keyname, rec_str_orig);
13188 
13189  return DB_STRUCT_MISMATCH;
13190  }
13191 
13192  status = db_get_key(hDB, hKeyTest, &key);
13193  assert(status == DB_SUCCESS);
13194 
13195  bad_string_length = 0;
13196 
13197  if (key.type == TID_STRING) {
13198  //printf("key name [%s], tid %d/%d, num_values %d/%d, string length %d/%d\n", key_name, key.type, tid, key.num_values, n_data, string_length, key.item_size);
13199  if (string_length > 0 && string_length != key.item_size) {
13200  bad_string_length = 1;
13201  }
13202  }
13203 
13204  /* check rec_str vs. ODB key */
13205  if (!equal_ustring(key.name, key_name) || key.type != tid || key.num_values != n_data || bad_string_length) {
13206  //printf("miscompare key name [%s], tid %d/%d, num_values %d/%d, string length %d/%d\n", key_name, key.type, tid, key.num_values, n_data, key.item_size, string_length);
13207  if (correct)
13208  return db_create_record(hDB, hKey, keyname, rec_str_orig);
13209 
13210  return DB_STRUCT_MISMATCH;
13211  }
13212 
13213  /* get next key in ODB */
13214  db_get_next_link(hDB, hKeyTest, &hKeyTest);
13215  }
13216  }
13217  }
13218  } while (TRUE);
13219 
13220  return DB_SUCCESS;
13221 }
#define DB_STRUCT_MISMATCH
Definition: midas.h:660
#define DB_NO_KEY
Definition: midas.h:648
#define DB_TRUNCATED
Definition: midas.h:650
unsigned int DWORD
Definition: mcstd.h:51
#define TID_KEY
Definition: midas.h:356
#define TID_LINK
Definition: midas.h:357
#define TID_LAST
Definition: midas.h:361
#define MAX_STRING_LENGTH
Definition: msystem.h:113
BOOL equal_ustring(const char *str1, const char *str2)
Definition: odb.cxx:3191
INT db_get_next_link(HNDLE hDB, HNDLE hKey, HNDLE *subkey_handle)
Definition: odb.cxx:5806
INT db_get_key(HNDLE hDB, HNDLE hKey, KEY *key)
Definition: odb.cxx:6009
INT db_find_key(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
Definition: odb.cxx:4069
INT db_create_record(HNDLE hDB, HNDLE hKey, const char *orig_key_name, const char *init_str)
Definition: odb.cxx:12803
const char * rpc_tid_name(INT id)
Definition: midas.cxx:11731
const char * rpc_tid_name_old(INT id)
Definition: midas.cxx:11738
#define RPC_DB_CHECK_RECORD
Definition: mrpc.h:89
KEY key
Definition: mdump.cxx:37
INT HNDLE
Definition: midas.h:132
#define POINTER_T
Definition: midas.h:166
size_t EXPRT strlcpy(char *dst, const char *src, size_t size)
INT j
Definition: odbhist.cxx:40
INT num_values
Definition: midas.h:1034
DWORD type
Definition: midas.h:1033
INT item_size
Definition: midas.h:1038
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_check_set_data_index_locked()

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

Definition at line 7142 of file odb.cxx.

7143 {
7144  /* check for write access */
7145  if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
7146  return DB_NO_ACCESS;
7147  }
7148 
7149  if (pkey->type != type) {
7150  db_msg(msg, MERROR, caller, "\"%s\" is of type %s, not %s", db_get_path_locked(pheader, pkey).c_str(), rpc_tid_name(pkey->type), rpc_tid_name(type));
7151  return DB_TYPE_MISMATCH;
7152  }
7153 
7154  /* keys cannot contain data */
7155  if (pkey->type == TID_KEY) {
7156  db_msg(msg, MERROR, "db_set_data_index", "\"%s\" of type TID_KEY cannot contain data", db_get_path_locked(pheader, pkey).c_str());
7157  return DB_TYPE_MISMATCH;
7158  }
7159 
7160  /* check utf-8 encoding */
7161  if (pkey->type == TID_STRING || pkey->type == TID_LINK) {
7162  //printf("db_check_set_data_index for %s: utf8 check for odb \"%s\" value \"%s\"\n", caller, db_get_path_locked(pheader, pkey).c_str(), data);
7163  const char* value = (const char*)data;
7164  if (!is_utf8(value)) {
7165  db_msg(msg, MERROR, "db_set_data_index", "\"%s\" index %d set to invalid UTF-8 Unicode string value \"%s\"", db_get_path_locked(pheader, pkey).c_str(), idx, value);
7166  // just a warning for now. K.O.
7167  //return DB_TYPE_MISMATCH;
7168  }
7169  }
7170 
7171  /* check for valid idx */
7172  if (idx < 0) {
7173  db_msg(msg, MERROR, caller, "\%s\" given invalid index %d", db_get_path_locked(pheader, pkey).c_str(), idx);
7174  return DB_INVALID_PARAM;
7175  }
7176 
7177  /* check for valid array element size: if new element size
7178  is different from existing size, ODB becomes corrupted */
7179  if (pkey->item_size != 0 && data_size != pkey->item_size) {
7180  db_msg(msg, MERROR, caller, "\"%s\" invalid element data size %d, expected %d", db_get_path_locked(pheader, pkey).c_str(), data_size, pkey->item_size);
7181  return DB_TYPE_MISMATCH;
7182  }
7183 
7184  return DB_SUCCESS;
7185 }
#define DB_INVALID_PARAM
Definition: midas.h:645
#define DB_NO_ACCESS
Definition: midas.h:654
#define DB_TYPE_MISMATCH
Definition: midas.h:651
static std::string db_get_path_locked(const DATABASE_HEADER *pheader, HNDLE hKey)
Definition: odb.cxx:4952
static bool is_utf8(const char *string)
Definition: odb.cxx:825
void * data
Definition: mana.cxx:268
INT type
Definition: mana.cxx:269
double value[100]
Definition: odbhist.cxx:42
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_check_set_data_locked()

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 
)
static

Definition at line 7095 of file odb.cxx.

7096 {
7097  /* check for write access */
7098  if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
7099  return DB_NO_ACCESS;
7100  }
7101 
7102  if (pkey->type != type) {
7103  db_msg(msg, MERROR, caller, "\"%s\" is of type %s, not %s", db_get_path_locked(pheader, pkey).c_str(), rpc_tid_name(pkey->type), rpc_tid_name(type));
7104  return DB_TYPE_MISMATCH;
7105  }
7106 
7107  /* keys cannot contain data */
7108  if (pkey->type == TID_KEY) {
7109  db_msg(msg, MERROR, caller, "\"%s\" of type TID_KEY cannot contain data", db_get_path_locked(pheader, pkey).c_str());
7110  return DB_TYPE_MISMATCH;
7111  }
7112 
7113  if (type == TID_STRING || type == TID_LINK) {
7114  if (num_values > 1) {
7115  int item_size = pkey->item_size;
7116  if (data_size > 0 && num_values > 0)
7117  item_size = data_size/num_values;
7118  //printf("db_check_set_data for %s: utf8 check for odb \"%s\" string array size %d, item size %d\n", caller, db_get_path_locked(pheader, pkey).c_str(), num_values, item_size);
7119  for (int i=0; i<num_values; i++) {
7120  const char* value = ((const char*)data) + i * item_size;
7121  //printf("db_check_set_data for %s: utf8 check for odb \"%s\" string array size %d item_size %d, index %d, value \"%s\"\n", caller, db_get_path_locked(pheader, pkey).c_str(), num_values, item_size, i, value);
7122  if (!is_utf8(value)) {
7123  db_msg(msg, MERROR, caller, "\"%s\" index %d set to invalid UTF-8 Unicode string value \"%s\"", db_get_path_locked(pheader, pkey).c_str(), i, value);
7124  // just a warning for now. K.O.
7125  //return DB_TYPE_MISMATCH;
7126  }
7127  }
7128  } else {
7129  const char* value = (const char*)data;
7130  //printf("db_check_set_data for %s: utf8 check for odb \"%s\" value \"%s\" size %d\n", caller, db_get_path_locked(pheader, pkey).c_str(), value, data_size);
7131  if (!is_utf8(value)) {
7132  db_msg(msg, MERROR, caller, "\"%s\" set to invalid UTF-8 Unicode string value \"%s\"", db_get_path_locked(pheader, pkey).c_str(), value);
7133  // just a warning for now. K.O.
7134  //return DB_TYPE_MISMATCH;
7135  }
7136  }
7137  }
7138 
7139  return DB_SUCCESS;
7140 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_cleanup()

void db_cleanup ( const char *  who,
DWORD  actual_time,
BOOL  wrong_interval 
)

Definition at line 2817 of file odb.cxx.

2818 {
2819 #ifdef LOCAL_ROUTINES
2820  int i;
2821  /* check online databases */
2822  for (i = 0; i < _database_entries; i++) {
2823  DATABASE *pdb = &_database[i];
2824  if (!pdb->attached) // empty slot
2825  continue;
2826 
2827  db_lock_database(i + 1);
2828  db_allow_write_locked(pdb, "db_cleanup");
2829 
2830  DATABASE_HEADER* pheader = pdb->database_header;
2831  DATABASE_CLIENT* pclient = db_get_my_client_locked(pdb);
2832 
2833  /* update the last_activity entry to show that we are alive */
2834  pclient->last_activity = actual_time;
2835 
2836  /* don't check other clients if interval is stange */
2837  if (wrong_interval) {
2838  db_unlock_database(i + 1);
2839  continue;
2840  }
2841 
2842  db_err_msg *msg = NULL;
2843 
2844  /* now check other clients */
2845  int j;
2846  for (j = 0; j < pheader->max_client_index; j++) {
2847  DATABASE_CLIENT *pdbclient = &pheader->client[j];
2848  int client_pid = pdbclient->pid;
2849  if (client_pid == 0) // empty slot
2850  continue;
2851 
2852  if (!ss_pid_exists(client_pid)) {
2853  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);
2854 
2855  db_delete_client_wlocked(pheader, j, &msg);
2856  db_delete_client_info_wlocked(i+1, pheader, client_pid, &msg);
2857 
2858  continue;
2859  }
2860 
2861  /* now make again the check with the buffer locked */
2863  if ((pdbclient->watchdog_timeout &&
2864  actual_time > pdbclient->last_activity &&
2865  actual_time - pdbclient->last_activity > pdbclient->watchdog_timeout)
2866  ) {
2867  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)",
2868  pdbclient->name, pheader->name, client_pid,
2869  who,
2870  (actual_time - pdbclient->last_activity) / 1000.0,
2871  pdbclient->watchdog_timeout / 1000.0);
2872 
2873  db_delete_client_wlocked(pheader, j, &msg);
2874  db_delete_client_info_wlocked(i+1, pheader, client_pid, &msg);
2875  }
2876  }
2877 
2878  db_unlock_database(i + 1);
2879  if (msg)
2880  db_flush_msg(&msg);
2881  }
2882 #endif
2883 }
DWORD ss_millitime()
Definition: system.cxx:3332
static void db_delete_client_wlocked(DATABASE_HEADER *pheader, int jclient, db_err_msg **msg)
Definition: odb.cxx:2715
DWORD actual_time
Definition: mfe.cxx:38
DWORD last_activity
Definition: msystem.h:417
char name[NAME_LENGTH]
Definition: msystem.h:411
DWORD watchdog_timeout
Definition: msystem.h:418
char name[NAME_LENGTH]
Definition: msystem.h:426
BOOL attached
Definition: msystem.h:444
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_cleanup2()

void db_cleanup2 ( const char *  client_name,
int  ignore_timeout,
DWORD  actual_time,
const char *  who 
)

Definition at line 2887 of file odb.cxx.

2888 {
2889  /* check online databases */
2890  int i;
2891  for (i = 0; i < _database_entries; i++) {
2892  if (_database[i].attached) {
2893  /* update the last_activity entry to show that we are alive */
2894 
2895  db_lock_database(i + 1);
2896 
2897  db_err_msg *msg = NULL;
2898 
2899  DATABASE* pdb = &_database[i];
2900 
2901  db_allow_write_locked(pdb, "db_cleanup2");
2902 
2903  DWORD now = ss_millitime();
2904 
2905  DATABASE_HEADER* pheader = pdb->database_header;
2906  DATABASE_CLIENT* pclient = db_get_my_client_locked(pdb);
2907  pclient->last_activity = now;
2908 
2909  /* now check other clients */
2910  int j;
2911  for (j = 0; j < pheader->max_client_index; j++) {
2912  DATABASE_CLIENT* pdbclient = &pheader->client[j];
2913  if (j == pdb->client_index) // do not check ourselves
2914  continue;
2915  if (!pdbclient->pid) // empty slot
2916  continue;
2917  if ((client_name == NULL || client_name[0] == 0
2918  || strncmp(pdbclient->name, client_name, strlen(client_name)) == 0)) {
2919  int client_pid = pdbclient->pid;
2920 
2921  if (!ss_pid_exists(client_pid)) {
2922  db_msg(&msg, MINFO, "db_cleanup2", "Client \'%s\' on database \'%s\' pid %d does not exist and db_cleanup2 called by %s removed it",
2923  pdbclient->name, pheader->name,
2924  client_pid,
2925  who);
2926 
2927  db_delete_client_wlocked(pheader, j, &msg);
2928  db_delete_client_info_wlocked(i+1, pheader, client_pid, &msg);
2929 
2930  /* go again though whole list */
2931  j = 0;
2932  continue;
2933  }
2934 
2935  DWORD interval;
2936  if (ignore_timeout)
2937  interval = 2 * WATCHDOG_INTERVAL;
2938  else
2939  interval = pdbclient->watchdog_timeout;
2940 
2941  /* If client process has no activity, clear its buffer entry. */
2942 
2943  if ((interval > 0 && now - pdbclient->last_activity > interval)) {
2944  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)",
2945  pdbclient->name, pheader->name,
2946  who,
2947  (now - pdbclient->last_activity) / 1000.0, interval / 1000.0);
2948 
2949  db_delete_client_wlocked(pheader, j, &msg);
2950  db_delete_client_info_wlocked(i+1, pheader, client_pid, &msg);
2951 
2952  /* go again though whole list */
2953  j = 0;
2954  continue;
2955  }
2956  }
2957  }
2958 
2959  db_unlock_database(i + 1);
2960  if (msg)
2961  db_flush_msg(&msg);
2962  }
2963  }
2964 }
#define WATCHDOG_INTERVAL
Definition: midas.h:295
INT client_index
Definition: msystem.h:445
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_close_all_databases()

INT EXPRT db_close_all_databases ( void  )

Definition at line 2351 of file odb.cxx.

2368 {
2369  INT status;
2370 
2371  if (rpc_is_remote()) {
2373  if (status != DB_SUCCESS)
2374  return status;
2375  }
2376 
2378  db_unwatch_all();
2379 
2380 #ifdef LOCAL_ROUTINES
2381  {
2382  INT i;
2383 
2384  for (i = _database_entries; i > 0; i--)
2386  }
2387 #endif /* LOCAL_ROUTINES */
2388 
2389  return DB_SUCCESS;
2390 }
INT db_close_all_records()
Definition: odb.cxx:13518
INT db_unwatch_all()
Definition: odb.cxx:13920
INT db_close_database(HNDLE hDB)
Definition: odb.cxx:2143
#define RPC_DB_CLOSE_ALL_DATABASES
Definition: mrpc.h:54
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_close_all_records()

INT db_close_all_records ( void  )

Release local memory for open records. This routines is called by db_close_all_databases() and cm_disconnect_experiment()

Returns
DB_SUCCESS, DB_INVALID_HANDLE

Definition at line 13518 of file odb.cxx.

13519 {
13520  INT i;
13521 
13522  for (i = 0; i < _record_list_entries; i++) {
13523  if (_record_list[i].handle) {
13524  if (_record_list[i].access_mode & MODE_WRITE) {
13525  free(_record_list[i].copy);
13526  _record_list[i].copy = NULL;
13527  }
13528 
13529  if (_record_list[i].access_mode & MODE_ALLOC) {
13530  free(_record_list[i].data);
13531  _record_list[i].data = NULL;
13532  }
13533 
13534  memset(&_record_list[i], 0, sizeof(RECORD_LIST));
13535  }
13536  }
13537 
13538  if (_record_list_entries > 0) {
13540  free(_record_list);
13541  _record_list = NULL;
13542  }
13543 
13544  return DB_SUCCESS;
13545 }
#define MODE_ALLOC
Definition: midas.h:381
static INT _record_list_entries
Definition: odb.cxx:62
static RECORD_LIST * _record_list
Definition: odb.cxx:61
void * data
Definition: msystem.h:468
void * copy
Definition: msystem.h:469
Here is the caller graph for this function:

◆ db_close_database()

INT EXPRT db_close_database ( HNDLE  hDB)

Close a database

Parameters
hDBODB handle obtained via cm_get_experiment_database().
Returns
DB_SUCCESS, DB_INVALID_HANDLE, RPC_NET_ERROR

Definition at line 2143 of file odb.cxx.

2144 {
2145  if (rpc_is_remote())
2147 
2148 #ifdef LOCAL_ROUTINES
2149  else {
2150  INT destroy_flag, i, j;
2151  char xname[256];
2152 
2153  if (hDB > _database_entries || hDB <= 0) {
2154  cm_msg(MERROR, "db_close_database", "invalid database handle %d", hDB);
2155  return DB_INVALID_HANDLE;
2156  }
2157 
2158  /* flush database to disk */
2160 
2161  /* first lock database */
2163 
2164  DATABASE* pdb = &_database[hDB - 1];
2165 
2166  if (!pdb->attached) {
2168  cm_msg(MERROR, "db_close_database", "database not attached");
2169  return DB_INVALID_HANDLE;
2170  }
2171 
2172  DATABASE_HEADER *pheader = pdb->database_header;
2173  DATABASE_CLIENT *pclient = db_get_my_client_locked(pdb);
2174 
2175  db_allow_write_locked(&_database[hDB-1], "db_close_database");
2176 
2177  /* close all open records */
2178  for (i = 0; i < pclient->max_index; i++)
2179  if (pclient->open_record[i].handle)
2180  db_remove_open_record_wlocked(pdb, pheader, pclient->open_record[i].handle);
2181 
2182  /* mark entry in _database as empty */
2183  pdb->attached = FALSE;
2184 
2185  /* clear entry from client structure in database header */
2186  memset(pclient, 0, sizeof(DATABASE_CLIENT));
2187 
2188  /* calculate new max_client_index entry */
2189  for (i = MAX_CLIENTS - 1; i >= 0; i--)
2190  if (pheader->client[i].pid != 0)
2191  break;
2192  pheader->max_client_index = i + 1;
2193 
2194  /* count new number of clients */
2195  for (i = MAX_CLIENTS - 1, j = 0; i >= 0; i--)
2196  if (pheader->client[i].pid != 0)
2197  j++;
2198  pheader->num_clients = j;
2199 
2200  destroy_flag = (pheader->num_clients == 0);
2201 
2202  /* flush shared memory to disk before it gets deleted */
2203  if (destroy_flag)
2204  ss_shm_flush(pheader->name, pdb->shm_adr, pdb->shm_size, pdb->shm_handle, true);
2205 
2206  strlcpy(xname, pheader->name, sizeof(xname));
2207 
2208  /* unmap shared memory, delete it if we are the last */
2209  ss_shm_close(xname, pdb->shm_adr, pdb->shm_size, pdb->shm_handle, destroy_flag);
2210 
2211  pheader = NULL; // after ss_shm_close(), pheader points nowhere
2212  pdb->database_header = NULL; // ditto
2213 
2214  /* unlock database */
2216 
2217  /* delete semaphore */
2218  ss_semaphore_delete(pdb->semaphore, destroy_flag);
2219 
2220  /* delete mutex */
2221  ss_mutex_delete(pdb->mutex);
2222 
2223  /* update _database_entries */
2224  if (hDB == _database_entries)
2226 
2227  if (_database_entries > 0)
2228  _database = (DATABASE *) realloc(_database, sizeof(DATABASE) * (_database_entries));
2229  else {
2230  free(_database);
2231  _database = NULL;
2232  }
2233 
2234  /* if we are the last one, also delete other semaphores */
2235  if (destroy_flag) {
2236  //extern INT _semaphore_elog, _semaphore_alarm, _semaphore_history, _semaphore_msg;
2238 
2239  if (_semaphore_elog)
2241  if (_semaphore_alarm)
2243  if (_semaphore_history)
2245  //if (_semaphore_msg)
2246  // ss_semaphore_delete(_semaphore_msg, TRUE);
2247  }
2248 
2249  }
2250 #endif /* LOCAL_ROUTINES */
2251 
2252  return DB_SUCCESS;
2253 }
#define FALSE
Definition: cfortran.h:309
INT ss_shm_flush(const char *name, const void *adr, size_t size, HNDLE handle, bool wait_for_thread)
Definition: system.cxx:1182
INT ss_mutex_delete(MUTEX_T *mutex)
Definition: system.cxx:3150
INT ss_semaphore_delete(HNDLE semaphore_handle, INT destroy_flag)
Definition: system.cxx:2808
INT ss_shm_close(const char *name, void *adr, size_t shm_size, HNDLE handle, INT destroy_flag)
Definition: system.cxx:764
INT db_flush_database(HNDLE hDB)
Definition: odb.cxx:2259
static int db_remove_open_record_wlocked(DATABASE *pdb, DATABASE_HEADER *pheader, HNDLE hKey)
Definition: odb.cxx:12456
#define RPC_DB_CLOSE_DATABASE
Definition: mrpc.h:53
INT _semaphore_alarm
Definition: midas.cxx:1464
INT _semaphore_elog
Definition: midas.cxx:1465
INT _semaphore_history
Definition: midas.cxx:1466
#define MAX_CLIENTS
Definition: midas.h:281
MUTEX_T * mutex
Definition: msystem.h:456
HNDLE semaphore
Definition: msystem.h:448
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_close_record()

INT EXPRT db_close_record ( HNDLE  hDB,
HNDLE  hKey 
)

Close a record previously opend with db_open_record.

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
Returns
DB_SUCCESS, DB_INVALID_HANDLE

Definition at line 13477 of file odb.cxx.

13478 {
13479 #ifdef LOCAL_ROUTINES
13480  {
13481  INT i;
13482 
13483  for (i = 0; i < _record_list_entries; i++)
13484  if (_record_list[i].handle == hKey && _record_list[i].hDB == hDB)
13485  break;
13486 
13487  if (i == _record_list_entries)
13488  return DB_INVALID_HANDLE;
13489 
13490  /* remove record entry from database structure */
13492 
13493  /* free local memory */
13494  if (_record_list[i].access_mode & MODE_ALLOC) {
13495  free(_record_list[i].data);
13496  _record_list[i].data = NULL;
13497  }
13498 
13499  if (_record_list[i].access_mode & MODE_WRITE) {
13500  free(_record_list[i].copy);
13501  _record_list[i].copy = NULL;
13502  }
13503 
13504  memset(&_record_list[i], 0, sizeof(RECORD_LIST));
13505  }
13506 #endif /* LOCAL_ROUTINES */
13507 
13508  return DB_SUCCESS;
13509 }
INT db_remove_open_record(HNDLE hDB, HNDLE hKey, BOOL lock)
Definition: odb.cxx:12502
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_copy()

INT EXPRT db_copy ( HNDLE  hDB,
HNDLE  hKey,
char *  buffer,
INT buffer_size,
const char *  path 
)

Copy an ODB subtree in ASCII format to a buffer

This function converts the binary ODB contents to an ASCII. The function db_paste() can be used to convert the ASCII representation back to binary ODB contents. The functions db_load() and db_save() internally use db_copy() and db_paste(). This function converts the binary ODB contents to an ASCII representation of the form:

  • For single value:
    [ODB path]
  • For strings:
    key name = STRING : [size] string contents
    @ STRING
    Definition: test_init.cxx:7
  • For arrayes (type can be BYTE, SBYTE, CHAR, WORD, SHORT, DWORD, INT, BOOL, FLOAT, DOUBLE, STRING or LINK):
    key name = type[size] :
    [0] value0
    [1] value1
    [2] value2
    ...
    Parameters
    hDBODB handle obtained via cm_get_experiment_database().
    hKeyHandle for key where search starts, zero for root.
    bufferASCII buffer which receives ODB contents.
    buffer_sizeSize of buffer, returns remaining space in buffer.
    pathInternal use only, must be empty ("").
    Returns
    DB_SUCCESS, DB_TRUNCATED, DB_NO_MEMORY

Definition at line 8211 of file odb.cxx.

8212 {
8213  INT i, j, size, status;
8214  KEY key;
8215  HNDLE hSubkey;
8216  char full_path[MAX_ODB_PATH];
8217  char *data;
8218  char line[MAX_STRING_LENGTH * 2];
8219  BOOL bWritten;
8220 
8221  strlcpy(full_path, path, sizeof(full_path));
8222 
8223  bWritten = FALSE;
8224 
8225  /* first enumerate this level */
8226  for (i = 0;; i++) {
8227  db_enum_link(hDB, hKey, i, &hSubkey);
8228 
8229  if (i == 0 && !hSubkey) {
8230  /* If key has no subkeys, just write this key */
8231  status = db_get_link(hDB, hKey, &key);
8232  if (status != DB_SUCCESS)
8233  continue;
8234  size = key.total_size;
8235  data = (char *) malloc(size);
8236  if (data == NULL) {
8237  cm_msg(MERROR, "db_copy", "cannot allocate data buffer");
8238  return DB_NO_MEMORY;
8239  }
8240  line[0] = 0;
8241 
8242  if (key.type != TID_KEY) {
8243  status = db_get_link_data(hDB, hKey, data, &size, key.type);
8244  if (status != DB_SUCCESS)
8245  continue;
8246  if (key.num_values == 1) {
8247  sprintf(line, "%s = %s : ", key.name, rpc_tid_name(key.type));
8248 
8249  if (key.type == TID_STRING && strchr(data, '\n') != NULL) {
8250  /* multiline string */
8251  sprintf(line + strlen(line), "[====#$@$#====]\n");
8252 
8253  /* copy line to buffer */
8254  if ((INT) (strlen(line) + 1) > *buffer_size) {
8255  free(data);
8256  return DB_TRUNCATED;
8257  }
8258 
8259  strcpy(buffer, line);
8260  buffer += strlen(line);
8261  *buffer_size -= strlen(line);
8262 
8263  /* copy multiple lines to buffer */
8264  if (key.item_size > *buffer_size) {
8265  free(data);
8266  return DB_TRUNCATED;
8267  }
8268 
8269  strcpy(buffer, data);
8270  buffer += strlen(data);
8271  *buffer_size -= strlen(data);
8272 
8273  strcpy(line, "\n====#$@$#====\n");
8274  } else {
8275  char str[MAX_STRING_LENGTH]; // buffer for db_sprintf()
8277 
8278  if (key.type == TID_STRING || key.type == TID_LINK)
8279  sprintf(line + strlen(line), "[%d] ", key.item_size);
8280 
8281  sprintf(line + strlen(line), "%s\n", str);
8282  }
8283  } else {
8284  char str[MAX_STRING_LENGTH]; // buffer for db_sprintf()
8285  sprintf(line, "%s = %s[%d] :\n", key.name, rpc_tid_name(key.type), key.num_values);
8286 
8287  for (j = 0; j < key.num_values; j++) {
8288  if (key.type == TID_STRING || key.type == TID_LINK)
8289  sprintf(line + strlen(line), "[%d] ", key.item_size);
8290  else
8291  sprintf(line + strlen(line), "[%d] ", j);
8292 
8294  sprintf(line + strlen(line), "%s\n", str);
8295 
8296  /* copy line to buffer */
8297  if ((INT) (strlen(line) + 1) > *buffer_size) {
8298  free(data);
8299  return DB_TRUNCATED;
8300  }
8301 
8302  strcpy(buffer, line);
8303  buffer += strlen(line);
8304  *buffer_size -= strlen(line);
8305  line[0] = 0;
8306  }
8307  }
8308  }
8309 
8310  /* copy line to buffer */
8311  if ((INT) (strlen(line) + 1) > *buffer_size) {
8312  free(data);
8313  return DB_TRUNCATED;
8314  }
8315 
8316  strcpy(buffer, line);
8317  buffer += strlen(line);
8318  *buffer_size -= strlen(line);
8319 
8320  free(data);
8321  data = NULL;
8322  }
8323 
8324  if (!hSubkey)
8325  break;
8326 
8328  if (status != DB_SUCCESS)
8329  continue;
8330 
8331  if (strcmp(key.name, "arr2") == 0)
8332  printf("\narr2\n");
8333  size = key.total_size;
8334  data = (char *) malloc(size);
8335  if (data == NULL) {
8336  cm_msg(MERROR, "db_copy", "cannot allocate data buffer");
8337  return DB_NO_MEMORY;
8338  }
8339 
8340  line[0] = 0;
8341 
8342  if (key.type == TID_KEY) {
8343  char str[MAX_ODB_PATH];
8344 
8345  /* new line */
8346  if (bWritten) {
8347  if (*buffer_size < 2) {
8348  free(data);
8349  return DB_TRUNCATED;
8350  }
8351 
8352  strcpy(buffer, "\n");
8353  buffer += 1;
8354  *buffer_size -= 1;
8355  }
8356 
8357  strcpy(str, full_path);
8358  if (str[0] && str[strlen(str) - 1] != '/')
8359  strcat(str, "/");
8360  strcat(str, key.name);
8361 
8362  /* recurse */
8363  status = db_copy(hDB, hSubkey, buffer, buffer_size, str);
8364  if (status != DB_SUCCESS) {
8365  free(data);
8366  return status;
8367  }
8368 
8369  buffer += strlen(buffer);
8370  bWritten = FALSE;
8371  } else {
8373  if (status != DB_SUCCESS)
8374  continue;
8375 
8376  if (!bWritten) {
8377  if (path[0] == 0)
8378  sprintf(line, "[.]\n");
8379  else
8380  sprintf(line, "[%s]\n", path);
8381  bWritten = TRUE;
8382  }
8383 
8384  if (key.num_values == 1) {
8385  sprintf(line + strlen(line), "%s = %s : ", key.name, rpc_tid_name(key.type));
8386 
8387  if (key.type == TID_STRING && strchr(data, '\n') != NULL) {
8388  /* multiline string */
8389  sprintf(line + strlen(line), "[====#$@$#====]\n");
8390 
8391  /* ensure string limiter */
8392  data[size - 1] = 0;
8393 
8394  /* copy line to buffer */
8395  if ((INT) (strlen(line) + 1) > *buffer_size) {
8396  free(data);
8397  return DB_TRUNCATED;
8398  }
8399 
8400  strcpy(buffer, line);
8401  buffer += strlen(line);
8402  *buffer_size -= strlen(line);
8403 
8404  /* copy multiple lines to buffer */
8405  if (key.item_size > *buffer_size) {
8406  free(data);
8407  return DB_TRUNCATED;
8408  }
8409 
8410  strcpy(buffer, data);
8411  buffer += strlen(data);
8412  *buffer_size -= strlen(data);
8413 
8414  strcpy(line, "\n====#$@$#====\n");
8415  } else {
8416  char str[MAX_STRING_LENGTH]; // buffer for db_sprintf()
8417 
8419 
8420  if (key.type == TID_STRING || key.type == TID_LINK)
8421  sprintf(line + strlen(line), "[%d] ", key.item_size);
8422 
8423  sprintf(line + strlen(line), "%s\n", str);
8424  }
8425  } else {
8426  sprintf(line + strlen(line), "%s = %s[%d] :\n", key.name, rpc_tid_name(key.type), key.num_values);
8427 
8428  for (j = 0; j < key.num_values; j++) {
8429  char str[MAX_STRING_LENGTH]; // buffer for db_sprintf()
8430 
8431  if (key.type == TID_STRING || key.type == TID_LINK)
8432  sprintf(line + strlen(line), "[%d] ", key.item_size);
8433  else
8434  sprintf(line + strlen(line), "[%d] ", j);
8435 
8437  sprintf(line + strlen(line), "%s\n", str);
8438 
8439  /* copy line to buffer */
8440  if ((INT) (strlen(line) + 1) > *buffer_size) {
8441  free(data);
8442  return DB_TRUNCATED;
8443  }
8444 
8445  strcpy(buffer, line);
8446  buffer += strlen(line);
8447  *buffer_size -= strlen(line);
8448  line[0] = 0;
8449  }
8450  }
8451 
8452  /* copy line to buffer */
8453  if ((INT) (strlen(line) + 1) > *buffer_size) {
8454  free(data);
8455  return DB_TRUNCATED;
8456  }
8457 
8458  strcpy(buffer, line);
8459  buffer += strlen(line);
8460  *buffer_size -= strlen(line);
8461  }
8462 
8463  free(data);
8464  data = NULL;
8465  }
8466 
8467  if (bWritten) {
8468  if (*buffer_size < 2)
8469  return DB_TRUNCATED;
8470 
8471  strcpy(buffer, "\n");
8472  buffer += 1;
8473  *buffer_size -= 1;
8474  }
8475 
8476  return DB_SUCCESS;
8477 }
INT db_copy(HNDLE hDB, HNDLE hKey, char *buffer, INT *buffer_size, const char *path)
Definition: odb.cxx:8211
INT db_get_link(HNDLE hDB, HNDLE hKey, KEY *key)
Definition: odb.cxx:6062
INT db_enum_link(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
Definition: odb.cxx:5715
INT db_sprintf(char *string, const void *data, INT data_size, INT idx, DWORD type)
Definition: odb.cxx:10847
INT db_get_link_data(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, DWORD type)
Definition: odb.cxx:6646
HNDLE hSubkey
Definition: mdump.cxx:38
DWORD BOOL
Definition: midas.h:105
#define MAX_ODB_PATH
Definition: midas.h:284
char str[256]
Definition: odbhist.cxx:33
INT total_size
Definition: midas.h:1037
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_copy_json_array()

INT EXPRT db_copy_json_array ( HNDLE  hDB,
HNDLE  hKey,
char **  buffer,
int *  buffer_size,
int *  buffer_end 
)

Copy an ODB array in JSON format to a buffer

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key
bufferreturns pointer to ASCII buffer with ODB contents
buffer_sizereturns size of ASCII buffer
buffer_endreturns number of bytes contained in buffer
Returns
DB_SUCCESS, DB_NO_MEMORY

Definition at line 10154 of file odb.cxx.

10155 {
10156  int size, asize;
10157  int status;
10158  char* data;
10159  int i;
10160  KEY key;
10161 
10162  status = db_get_key(hDB, hKey, &key);
10163  if (status != DB_SUCCESS)
10164  return status;
10165 
10166  assert(key.type != TID_KEY);
10167 
10168  if (key.num_values > 1) {
10169  json_write(buffer, buffer_size, buffer_end, 0, "[ ", 0);
10170  }
10171 
10172  size = key.total_size;
10173 
10174  asize = size;
10175  if (asize < 1024)
10176  asize = 1024;
10177 
10178  data = (char *) malloc(asize);
10179  if (data == NULL) {
10180  cm_msg(MERROR, "db_save_json_key_data", "cannot allocate data buffer for %d bytes", asize);
10181  return DB_NO_MEMORY;
10182  }
10183 
10184  data[0] = 0; // protect against TID_STRING that has key.total_size == 0.
10185 
10186  status = db_get_data(hDB, hKey, data, &size, key.type);
10187  if (status != DB_SUCCESS) {
10188  free(data);
10189  return status;
10190  }
10191 
10192  for (i = 0; i < key.num_values; i++) {
10193  char *p = data + key.item_size*i;
10194 
10195  if (i != 0)
10196  json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
10197 
10198  json_write_data(buffer, buffer_size, buffer_end, 0, &key, p);
10199  }
10200 
10201  if (key.num_values > 1) {
10202  json_write(buffer, buffer_size, buffer_end, 0, " ]", 0);
10203  }
10204 
10205  free(data);
10206  data = NULL;
10207 
10208  return DB_SUCCESS;
10209 }
INT db_get_data(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, DWORD type)
Definition: odb.cxx:6529
static void json_write_data(char **buffer, int *buffer_size, int *buffer_end, int level, const KEY *key, const char *p)
Definition: odb.cxx:9643
void json_write(char **buffer, int *buffer_size, int *buffer_end, int level, const char *s, int quoted)
Definition: odb.cxx:9528
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_copy_json_index()

INT EXPRT db_copy_json_index ( HNDLE  hDB,
HNDLE  hKey,
int  index,
char **  buffer,
int *  buffer_size,
int *  buffer_end 
)

Copy an ODB array element in JSON format to a buffer

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key
indexArray index
bufferreturns pointer to ASCII buffer with ODB contents
buffer_sizereturns size of ASCII buffer
buffer_endreturns number of bytes contained in buffer
Returns
DB_SUCCESS, DB_NO_MEMORY

Definition at line 10223 of file odb.cxx.

10224 {
10225  int status;
10226  KEY key;
10227 
10228  status = db_get_key(hDB, hKey, &key);
10229 
10230  if (status != DB_SUCCESS)
10231  return status;
10232 
10233  int size = key.item_size;
10234  char* data = (char*)malloc(size + 1); // extra byte for string NUL termination
10235  assert(data != NULL);
10236 
10238 
10239  if (status != DB_SUCCESS) {
10240  free(data);
10241  return status;
10242  }
10243 
10244  assert(size <= key.item_size);
10245  data[key.item_size] = 0; // make sure data is NUL terminated, in case of strings.
10246 
10247  json_write_data(buffer, buffer_size, buffer_end, 0, &key, data);
10248 
10249  free(data);
10250 
10251  return DB_SUCCESS;
10252 }
INT db_get_data_index(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT idx, DWORD type)
Definition: odb.cxx:6885
INT index
Definition: mana.cxx:271
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_copy_json_ls()

INT EXPRT db_copy_json_ls ( HNDLE  hDB,
HNDLE  hKey,
char **  buffer,
int *  buffer_size,
int *  buffer_end 
)

Definition at line 10425 of file odb.cxx.

10426 {
10427  int status;
10428  bool unlock = false;
10429 
10430  if (!rpc_is_remote()) {
10432  if (status != DB_SUCCESS) {
10433  return status;
10434  }
10435  unlock = true;
10436  }
10437 
10439 
10440  if (unlock) {
10442  }
10443 
10444  return status;
10445 }
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)
Definition: odb.cxx:10388
#define JS_LEVEL_0
Definition: midas.h:1717
#define JSFLAG_FOLLOW_LINKS
Definition: midas.h:1721
#define JS_MUST_BE_SUBDIR
Definition: midas.h:1719
#define JSFLAG_SAVE_KEYS
Definition: midas.h:1720
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_copy_json_obsolete()

INT EXPRT db_copy_json_obsolete ( HNDLE  hDB,
HNDLE  hKey,
char **  buffer,
int *  buffer_size,
int *  buffer_end,
int  save_keys,
int  follow_links,
int  recurse 
)

Copy an ODB subtree in JSON format to a buffer

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
bufferreturns pointer to ASCII buffer with ODB contents
buffer_sizereturns size of ASCII buffer
buffer_endreturns number of bytes contained in buffer
Returns
DB_SUCCESS, DB_NO_MEMORY

Definition at line 10512 of file odb.cxx.

10513 {
10514  db_save_json_key_obsolete(hDB, hKey, 0, buffer, buffer_size, buffer_end, save_keys, follow_links, recurse);
10515  json_write(buffer, buffer_size, buffer_end, 0, "\n", 0);
10516  return DB_SUCCESS;
10517 }
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)
Definition: odb.cxx:9812
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_copy_json_save()

INT EXPRT db_copy_json_save ( HNDLE  hDB,
HNDLE  hKey,
char **  buffer,
int *  buffer_size,
int *  buffer_end 
)

Definition at line 10479 of file odb.cxx.

10480 {
10481  int status;
10482  bool unlock = false;
10483 
10484  if (!rpc_is_remote()) {
10486  if (status != DB_SUCCESS) {
10487  return status;
10488  }
10489  unlock = true;
10490  }
10491 
10493 
10494  if (unlock) {
10496  }
10497 
10498  return status;
10499 }
#define JSFLAG_RECURSE
Definition: midas.h:1722
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_copy_json_values()

INT EXPRT 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 
)

Definition at line 10447 of file odb.cxx.

10448 {
10449  int status;
10450  int flags = JSFLAG_FOLLOW_LINKS|JSFLAG_RECURSE;
10451  if (omit_names)
10452  flags |= JSFLAG_OMIT_NAMES;
10453  if (omit_last_written)
10454  flags |= JSFLAG_OMIT_LAST_WRITTEN;
10455  if (omit_old_timestamp)
10456  flags |= JSFLAG_OMIT_OLD;
10457  if (!preserve_case)
10458  flags |= JSFLAG_LOWERCASE;
10459 
10460  bool unlock = false;
10461 
10462  if (!rpc_is_remote()) {
10464  if (status != DB_SUCCESS) {
10465  return status;
10466  }
10467  unlock = true;
10468  }
10469 
10470  status = json_write_anything(hDB, hKey, buffer, buffer_size, buffer_end, JS_LEVEL_0, 0, flags, omit_old_timestamp);
10471 
10472  if (unlock) {
10474  }
10475 
10476  return status;
10477 }
#define JSFLAG_LOWERCASE
Definition: midas.h:1723
#define JSFLAG_OMIT_LAST_WRITTEN
Definition: midas.h:1725
#define JSFLAG_OMIT_NAMES
Definition: midas.h:1724
#define JSFLAG_OMIT_OLD
Definition: midas.h:1726
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_copy_xml()

INT EXPRT db_copy_xml ( HNDLE  hDB,
HNDLE  hKey,
char *  buffer,
int *  buffer_size,
bool  header 
)

Copy an ODB subtree in XML format to a buffer

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
bufferASCII buffer which receives ODB contents.
buffer_sizeSize of buffer, returns remaining space in buffer.
Returns
DB_SUCCESS, DB_TRUNCATED, DB_NO_MEMORY

Definition at line 9037 of file odb.cxx.

9038 {
9039 
9040  if (rpc_is_remote())
9041  return rpc_call(RPC_DB_COPY_XML, hDB, hKey, buffer, buffer_size, header);
9042 
9043 #ifdef LOCAL_ROUTINES
9044  {
9045  INT len;
9046  char *p;
9047  MXML_WRITER *writer;
9048 
9049  /* open file */
9050  writer = mxml_open_buffer();
9051  if (writer == NULL) {
9052  cm_msg(MERROR, "db_copy_xml", "Cannot allocate buffer");
9053  return DB_NO_MEMORY;
9054  }
9055 
9056  if (header) {
9057  char str[256];
9058  db_get_path(hDB, hKey, str, sizeof(str));
9059 
9060  /* write XML header */
9061  mxml_start_element(writer, "odb");
9062  mxml_write_attribute(writer, "root", str);
9063  mxml_write_attribute(writer, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
9064  mxml_write_attribute(writer, "xsi:noNamespaceSchemaLocation", "http://midas.psi.ch/odb.xsd");
9065 
9066  db_save_xml_key(hDB, hKey, 0, writer);
9067  mxml_end_element(writer); // "odb"
9068  } else {
9069  KEY key;
9070  int status = db_get_key(hDB, hKey, &key);
9071  if (status != DB_SUCCESS)
9072  return status;
9073 
9074  db_save_xml_key(hDB, hKey, 1, writer);
9075  }
9076 
9077  p = mxml_close_buffer(writer);
9078  len = strlen(p) + 1;
9079  if (len > *buffer_size) {
9080  free(p);
9081  *buffer_size = 0;
9082  return DB_TRUNCATED;
9083  }
9084 
9085  strlcpy(buffer, p, len);
9086  free(p);
9087  *buffer_size = len;
9088  }
9089 #endif /* LOCAL_ROUTINES */
9090 
9091  return DB_SUCCESS;
9092 }
INT db_get_path(HNDLE hDB, HNDLE hKey, char *path, INT buf_size)
Definition: odb.cxx:4980
INT db_save_xml_key(HNDLE hDB, HNDLE hKey, INT level, MXML_WRITER *writer)
Definition: odb.cxx:9347
#define RPC_DB_COPY_XML
Definition: mrpc.h:98
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_create_key()

INT EXPRT db_create_key ( HNDLE  hDB,
HNDLE  hKey,
const char *  key_name,
DWORD  type 
)

Create a new key in a database

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyKey handle to start with, 0 for root
key_nameName of key in the form "/key/key/key"
typeType of key, one of TID_xxx (see Midas_Data_Types)
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_INVALID_PARAM, DB_FULL, DB_KEY_EXIST, DB_NO_ACCESS

Definition at line 3298 of file odb.cxx.

3299 {
3300 
3301  if (rpc_is_remote())
3302  return rpc_call(RPC_DB_CREATE_KEY, hDB, hKey, key_name, type);
3303 
3304 #ifdef LOCAL_ROUTINES
3305  {
3306  int status;
3307 
3308  if (hDB > _database_entries || hDB <= 0) {
3309  cm_msg(MERROR, "db_create_key", "invalid database handle");
3310  return DB_INVALID_HANDLE;
3311  }
3312 
3313  if (!_database[hDB - 1].attached) {
3314  cm_msg(MERROR, "db_create_key", "invalid database handle");
3315  return DB_INVALID_HANDLE;
3316  }
3317 
3318  /* lock database */
3320 
3321  DATABASE_HEADER* pheader = _database[hDB - 1].database_header;
3322 
3323  db_err_msg *msg = NULL;
3324 
3325  KEY* pkey = (KEY*)db_get_pkey(pheader, hKey, &status, "db_create_key", &msg);
3326 
3327  if (!pkey) {
3329  if (msg)
3330  db_flush_msg(&msg);
3331  return DB_INVALID_HANDLE;
3332  }
3333 
3334  db_allow_write_locked(&_database[hDB-1], "db_create_key");
3335 
3336  KEY* newpkey = NULL;
3337 
3338  status = db_create_key_wlocked(pheader, pkey, key_name, type, &newpkey, &msg);
3339 
3341 
3342  if (msg)
3343  db_flush_msg(&msg);
3344 
3345  return status;
3346  }
3347 #endif /* LOCAL_ROUTINES */
3348 
3349  return DB_SUCCESS;
3350 }
static int db_create_key_wlocked(DATABASE_HEADER *pheader, KEY *parentKey, const char *key_name, DWORD type, KEY **pnewkey, db_err_msg **msg)
Definition: odb.cxx:3354
#define RPC_DB_CREATE_KEY
Definition: mrpc.h:55
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_create_key_wlocked()

int db_create_key_wlocked ( DATABASE_HEADER pheader,
KEY parentKey,
const char *  key_name,
DWORD  type,
KEY **  pnewkey,
db_err_msg **  msg 
)
static

Definition at line 3354 of file odb.cxx.

3355 {
3356  int status;
3357 
3358  if (pnewkey)
3359  *pnewkey = NULL;
3360 
3361  if (parentKey== NULL) {
3362  parentKey = (KEY*) db_get_pkey(pheader, pheader->root_key, &status, "db_create_key_wlocked", msg);
3363  if (!parentKey) {
3364  return status;
3365  }
3366  }
3367 
3368  status = db_validate_name(key_name, TRUE, "db_create_key_wlocked", msg);
3369  if (status != DB_SUCCESS) {
3370  return status;
3371  }
3372 
3373  /* check type */
3374  if (type <= 0 || type >= TID_LAST) {
3375  db_msg(msg, MERROR, "db_create_key", "invalid key type %d to create \'%s\' in \'%s\'", type, key_name, db_get_path_locked(pheader, parentKey).c_str());
3376  return DB_INVALID_PARAM;
3377  }
3378 
3379  const KEY* pdir = parentKey;
3380 
3381  if (pdir->type != TID_KEY) {
3382  db_msg(msg, MERROR, "db_create_key", "cannot create \'%s\' in \'%s\' tid is %d, not a directory", key_name, db_get_path_locked(pheader, pdir).c_str(), pdir->type);
3383  return DB_NO_KEY;
3384  }
3385 
3386  KEY* pcreated = NULL;
3387 
3388  const char* pkey_name = key_name;
3389  do {
3390  // key name is limited to NAME_LENGTH, but buffer has to be slightly longer
3391  // to prevent truncation before db_validate_name checks for correct length. K.O.
3392  char name[NAME_LENGTH+100];
3393 
3394  /* extract single key from key_name */
3395  pkey_name = extract_key(pkey_name, name, sizeof(name));
3396 
3397  status = db_validate_name(name, FALSE, "db_create_key", msg);
3398  if (status != DB_SUCCESS) {
3399  return status;
3400  }
3401 
3402  /* do not allow empty names, like '/dir/dir//dir/' */
3403  if (name[0] == 0) {
3404  return DB_INVALID_PARAM;
3405  }
3406 
3407  /* check if parent or current directory */
3408  if (strcmp(name, "..") == 0) {
3409  pdir = db_get_parent(pheader, pdir, &status, "db_create_key", msg);
3410  if (!pdir) {
3411  return status;
3412  }
3413  continue;
3414  }
3415  if (strcmp(name, ".") == 0)
3416  continue;
3417 
3418  KEY* pprev = NULL;
3419  const KEY* pitem = db_enum_first_locked(pheader, pdir, msg);
3420 
3421  while (pitem) {
3422  if (equal_ustring(name, pitem->name)) {
3423  break;
3424  }
3425  pprev = (KEY*)pitem;
3426  pitem = db_enum_next_locked(pheader, pdir, pitem, msg);
3427  }
3428 
3429  if (!pitem) {
3430  /* not found: create new key */
3431 
3432  /* check parent for write access */
3433  const KEY* pkeyparent = db_get_parent(pheader, pdir, &status, "db_create_key", msg);
3434  if (!pkeyparent) {
3435  return status;
3436  }
3437 
3438  if (!(pkeyparent->access_mode & MODE_WRITE) || (pkeyparent->access_mode & MODE_EXCLUSIVE)) {
3439  return DB_NO_ACCESS;
3440  }
3441 
3442  KEYLIST* pkeylist = (KEYLIST*)db_get_pkeylist(pheader, db_pkey_to_hkey(pheader, pdir), pdir, "db_create_key_wlocked", msg);
3443 
3444  if (!pkeylist) {
3445  return DB_CORRUPTED;
3446  }
3447 
3448  pkeylist->num_keys++;
3449 
3450  if (*pkey_name == '/' || type == TID_KEY) {
3451  /* create new key with keylist */
3452  KEY* pkey = (KEY *) malloc_key(pheader, sizeof(KEY), "db_create_key_subdir");
3453 
3454  if (pkey == NULL) {
3455  if (pkeylist->num_keys > 0)
3456  pkeylist->num_keys--;
3457 
3458  db_msg(msg, MERROR, "db_create_key", "online database full while creating \'%s\' in \'%s\'", key_name, db_get_path_locked(pheader, parentKey).c_str());
3459  return DB_FULL;
3460  }
3461 
3462  /* append key to key list */
3463  if (pprev)
3464  pprev->next_key = (POINTER_T) pkey - (POINTER_T) pheader;
3465  else
3466  pkeylist->first_key = (POINTER_T) pkey - (POINTER_T) pheader;
3467 
3468  /* set key properties */
3469  pkey->type = TID_KEY;
3470  pkey->num_values = 1;
3472  strlcpy(pkey->name, name, sizeof(pkey->name));
3473  pkey->parent_keylist = (POINTER_T) pkeylist - (POINTER_T) pheader;
3474 
3475  /* find space for new keylist */
3476  pkeylist = (KEYLIST *) malloc_key(pheader, sizeof(KEYLIST), "db_create_key_B");
3477 
3478  if (pkeylist == NULL) {
3479  db_msg(msg, MERROR, "db_create_key", "online database full while creating \'%s\' in \'%s'", key_name, db_get_path_locked(pheader, parentKey).c_str());
3480  return DB_FULL;
3481  }
3482 
3483  /* store keylist in data field */
3484  pkey->data = (POINTER_T) pkeylist - (POINTER_T) pheader;
3485  pkey->item_size = sizeof(KEYLIST);
3486  pkey->total_size = sizeof(KEYLIST);
3487 
3488  pkeylist->parent = (POINTER_T) pkey - (POINTER_T) pheader;
3489  pkeylist->num_keys = 0;
3490  pkeylist->first_key = 0;
3491 
3492  pcreated = pkey;
3493  pdir = pkey; // descend into newly created subdirectory
3494  } else {
3495  /* create new key with data */
3496  KEY* pkey = (KEY *) malloc_key(pheader, sizeof(KEY), "db_create_key_data");
3497 
3498  if (pkey == NULL) {
3499  if (pkeylist->num_keys > 0)
3500  pkeylist->num_keys--;
3501 
3502  db_msg(msg, MERROR, "db_create_key", "online database full while creating \'%s\' in \'%s\'", key_name, db_get_path_locked(pheader, parentKey).c_str());
3503  return DB_FULL;
3504  }
3505 
3506  /* append key to key list */
3507  if (pprev)
3508  pprev->next_key = (POINTER_T) pkey - (POINTER_T) pheader;
3509  else
3510  pkeylist->first_key = (POINTER_T) pkey - (POINTER_T) pheader;
3511 
3512  pkey->type = type;
3513  pkey->num_values = 1;
3515  strlcpy(pkey->name, name, sizeof(pkey->name));
3516  pkey->parent_keylist = (POINTER_T) pkeylist - (POINTER_T) pheader;
3517 
3518  /* allocate data */
3519  pkey->item_size = rpc_tid_size(type);
3520  if (pkey->item_size > 0) {
3521  void* data = malloc_data(pheader, pkey->item_size);
3522  if (data == NULL) {
3523  pkey->total_size = 0;
3524  db_msg(msg, MERROR, "db_create_key", "online database full while creating \'%s\' in \'%s\'", key_name, db_get_path_locked(pheader, parentKey).c_str());
3525  return DB_FULL;
3526  }
3527 
3528  pkey->total_size = pkey->item_size;
3529  pkey->data = (POINTER_T)data - (POINTER_T)pheader;
3530  } else {
3531  /* first data is empty */
3532  pkey->item_size = 0;
3533  pkey->total_size = 0;
3534  pkey->data = 0;
3535  }
3536  pcreated = pkey;
3537  }
3538  } else {
3539  /* key found: descend */
3540 
3541  /* resolve links */
3542  if (pitem->type == TID_LINK && pkey_name[0]) {
3543  pdir = db_resolve_link_locked(pheader, pitem, &status, msg);
3544  if (!pdir) {
3545  return status;
3546  }
3547  continue;
3548  }
3549 
3550  if (!(*pkey_name == '/')) {
3551  if (pitem->type != type) {
3552  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_locked(pheader, pitem).c_str(), key_name, type, db_get_path_locked(pheader, parentKey).c_str());
3553  return DB_TYPE_MISMATCH;
3554  }
3555  //db_print_pkey(pheader, pitem);
3556 
3557  if (pnewkey)
3558  *pnewkey = (KEY*)pitem;
3559 
3560  return DB_KEY_EXIST;
3561  }
3562 
3563  if (pitem->type != TID_KEY) {
3564  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_locked(pheader, pitem).c_str(), key_name, db_get_path_locked(pheader, parentKey).c_str());
3565  return DB_TYPE_MISMATCH;
3566  }
3567 
3568  pdir = pitem;
3569  }
3570  } while (*pkey_name == '/');
3571 
3572  assert(pcreated != NULL);
3573 
3574  if (pnewkey)
3575  *pnewkey = pcreated;
3576 
3577  return DB_SUCCESS;
3578 }
#define DB_FULL
Definition: midas.h:646
#define DB_KEY_EXIST
Definition: midas.h:647
#define DB_CORRUPTED
Definition: midas.h:659
#define MODE_DELETE
Definition: midas.h:379
#define MODE_READ
Definition: midas.h:377
const char * extract_key(const char *key_list, char *key_name, int key_name_length)
Definition: odb.cxx:3177
static const KEY * db_enum_next_locked(const DATABASE_HEADER *pheader, const KEY *pdir, const KEY *pkey, db_err_msg **msg)
Definition: odb.cxx:1089
static const KEY * db_resolve_link_locked(const DATABASE_HEADER *, const KEY *, int *pstatus, db_err_msg **)
Definition: odb.cxx:1097
static const KEY * db_get_parent(const DATABASE_HEADER *pheader, const KEY *pkey, int *pstatus, const char *caller, db_err_msg **msg)
Definition: odb.cxx:1033
static void * malloc_data(DATABASE_HEADER *pheader, INT size)
Definition: odb.cxx:363
static const KEY * db_enum_first_locked(const DATABASE_HEADER *pheader, const KEY *pkey, db_err_msg **msg)
Definition: odb.cxx:1059
static HNDLE db_pkey_to_hkey(const DATABASE_HEADER *pheader, const KEY *pkey)
Definition: odb.cxx:1028
static void * malloc_key(DATABASE_HEADER *pheader, INT size, const char *caller)
Definition: odb.cxx:205
static int db_validate_name(const char *name, int maybe_path, const char *caller_name, db_err_msg **msg)
Definition: odb.cxx:836
static const KEYLIST * db_get_pkeylist(const DATABASE_HEADER *pheader, HNDLE hKey, const KEY *pkey, const char *caller, db_err_msg **msg, bool kludge_repair=false)
Definition: odb.cxx:985
INT rpc_tid_size(INT id)
Definition: midas.cxx:11724
#define NAME_LENGTH
Definition: midas.h:279
INT parent_keylist
Definition: midas.h:1042
INT next_key
Definition: midas.h:1041
INT data
Definition: midas.h:1036
INT num_keys
Definition: midas.h:1048
INT parent
Definition: midas.h:1047
INT first_key
Definition: midas.h:1049
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_create_link()

INT EXPRT db_create_link ( HNDLE  hDB,
HNDLE  hKey,
const char *  link_name,
const char *  destination 
)

Create a link to a key or set the destination of and existing link.

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyKey handle to start with, 0 for root
link_nameName of key in the form "/key/key/key"
destinationDestination of link in the form "/key/key/key"
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_FULL, DB_KEY_EXIST, DB_NO_ACCESS, DB_INVALID_NAME

Definition at line 3591 of file odb.cxx.

3592 {
3593  HNDLE hkey;
3594  int status;
3595 
3596  if (rpc_is_remote())
3597  return rpc_call(RPC_DB_CREATE_LINK, hDB, hKey, link_name, destination);
3598 
3599  if (destination == NULL) {
3600  cm_msg(MERROR, "db_create_link", "link destination name is NULL");
3601  return DB_INVALID_NAME;
3602  }
3603 
3604  if (destination[0] != '/') {
3605  cm_msg(MERROR, "db_create_link", "link destination name \'%s\' should start with \'/\', relative links are forbidden", destination);
3606  return DB_INVALID_NAME;
3607  }
3608 
3609  if (strlen(destination) < 1) {
3610  cm_msg(MERROR, "db_create_link", "link destination name \'%s\' is too short", destination);
3611  return DB_INVALID_NAME;
3612  }
3613 
3614  if ((destination[0] == '/') && (destination[1] == 0)) {
3615  cm_msg(MERROR, "db_create_link", "links to \"/\" are forbidden");
3616  return DB_INVALID_NAME;
3617  }
3618 
3619  /* check if destination exists */
3620  status = db_find_key(hDB, hKey, destination, &hkey);
3621  if (status != DB_SUCCESS) {
3622  cm_msg(MERROR, "db_create_link", "Link destination \"%s\" does not exist", destination);
3623  return DB_NO_KEY;
3624  }
3625 
3626  //printf("db_create_link: [%s] hkey %d\n", destination, hkey);
3627 
3628  /* check if link already exists */
3629  status = db_find_link(hDB, hKey, link_name, &hkey);
3630  if (status != DB_SUCCESS) {
3631  // create new link
3632  status = db_set_value(hDB, hKey, link_name, destination, strlen(destination) + 1, 1, TID_LINK);
3633  } else {
3634  // check if key is TID_LINK
3635  KEY key;
3636  db_get_key(hDB, hkey, &key);
3637  if (key.type != TID_LINK) {
3638  cm_msg(MERROR, "db_create_link", "Existing key \"%s\" is not a link", link_name);
3639  return DB_KEY_EXIST;
3640  }
3641 
3642  // modify existing link
3643  status = db_set_link_data(hDB, hkey, destination, strlen(destination)+1, 1, TID_LINK);
3644  }
3645 
3646  return status;
3647 }
#define DB_INVALID_NAME
Definition: midas.h:640
INT db_find_link(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
Definition: odb.cxx:4264
INT db_set_link_data(HNDLE hDB, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type)
Definition: odb.cxx:7419
INT db_set_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, const void *data, INT data_size, INT num_values, DWORD type)
Definition: odb.cxx:5251
#define RPC_DB_CREATE_LINK
Definition: mrpc.h:56
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_create_record()

INT EXPRT db_create_record ( HNDLE  hDB,
HNDLE  hKey,
const char *  orig_key_name,
const char *  init_str 
)

dox Create a record. If a part of the record exists alreay, merge it with the init_str (use values from the init_str only when they are not in the existing record).

This functions creates a ODB sub-tree according to an ASCII representation of that tree. See db_copy() for a description. It can be used to create a sub-tree which exactly matches a C structure. The sub-tree can then later mapped to the C structure ("hot-link") via the function db_open_record().

If a sub-tree exists already which exactly matches the ASCII representation, it is not modified. If part of the tree exists, it is merged with the ASCII representation where the ODB values have priority, only values not present in the ODB are created with the default values of the ASCII representation. It is therefore recommended that before creating an ODB hot-link the function db_create_record() is called to insure that the ODB tree and the C structure contain exactly the same values in the same order.

Following example creates a record under /Equipment/Trigger/Settings, opens a hot-link between that record and a local C structure trigger_settings and registers a callback function trigger_update() which gets called each time the record is changed.

struct {
INT level1;
INT level2;
char *trigger_settings_str =
"[Settings]\n\
level1 = INT : 0\n\
level2 = INT : 0";
void trigger_update(INT hDB, INT hkey, void *info)
{
printf("New levels: %d %d\n",
}
{
HNDLE hDB, hkey;
char[128] info;
...
db_create_record(hDB, 0, "/Equipment/Trigger", trigger_settings_str);
db_find_key(hDB, 0,"/Equipment/Trigger/Settings", &hkey);
sizeof(trigger_settings), MODE_READ, trigger_update, info);
...
}
TRIGGER_SETTINGS trigger_settings
Definition: analyzer.cxx:52
INT cm_get_experiment_database(HNDLE *hDB, HNDLE *hKeyClient)
Definition: midas.cxx:3005
INT db_open_record(HNDLE hDB, HNDLE hKey, void *ptr, INT rec_size, WORD access_mode, void(*dispatcher)(INT, INT, void *), void *info)
Definition: odb.cxx:13294
void ** info
Definition: fesimdaq.cxx:41
int main(int argc, char *argv[])
Definition: mana.cxx:5320
Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
orig_key_nameName of key to search, can contain directories.
init_strInitialization string in the format of the db_copy/db_save functions.
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_FULL, DB_NO_ACCESS, DB_OPEN_RECORD

Definition at line 12803 of file odb.cxx.

12804 {
12805  char str[256], key_name[256], *buffer;
12806  INT status, size, buffer_size;
12807  HNDLE hKeyTmp, hKeyTmpO, hKeyOrig, hSubkey;
12808 
12809  if (rpc_is_remote())
12810  return rpc_call(RPC_DB_CREATE_RECORD, hDB, hKey, orig_key_name, init_str);
12811 
12812  /* make this function atomic */
12814 
12815  /* strip trailing '/' */
12816  strlcpy(key_name, orig_key_name, sizeof(key_name));
12817  if (strlen(key_name) > 1 && key_name[strlen(key_name) - 1] == '/')
12818  key_name[strlen(key_name) - 1] = 0;
12819 
12820  /* merge temporay record and original record */
12821  status = db_find_key(hDB, hKey, key_name, &hKeyOrig);
12822  if (status == DB_SUCCESS) {
12823  assert(hKeyOrig != 0);
12824 #ifdef CHECK_OPEN_RECORD
12825  /* check if key or subkey is opened */
12826  _global_open_count = 0; // FIXME: this is not thread safe
12827  db_scan_tree_link(hDB, hKeyOrig, 0, check_open_keys, NULL);
12828  if (_global_open_count) {
12830  return DB_OPEN_RECORD;
12831  }
12832 #endif
12833  /* create temporary records */
12834  sprintf(str, "/System/Tmp/%sI", ss_tid_to_string(ss_gettid()).c_str());
12835  //printf("db_create_record str [%s]\n", str);
12836  db_find_key(hDB, 0, str, &hKeyTmp);
12837  if (hKeyTmp)
12838  db_delete_key(hDB, hKeyTmp, FALSE);
12839  db_create_key(hDB, 0, str, TID_KEY);
12840  status = db_find_key(hDB, 0, str, &hKeyTmp);
12841  if (status != DB_SUCCESS) {
12843  return status;
12844  }
12845 
12846  sprintf(str, "/System/Tmp/%sO", ss_tid_to_string(ss_gettid()).c_str());
12847  //printf("db_create_record str [%s]\n", str);
12848  db_find_key(hDB, 0, str, &hKeyTmpO);
12849  if (hKeyTmpO)
12850  db_delete_key(hDB, hKeyTmpO, FALSE);
12851  db_create_key(hDB, 0, str, TID_KEY);
12852  status = db_find_key(hDB, 0, str, &hKeyTmpO);
12853  if (status != DB_SUCCESS) {
12855  return status;
12856  }
12857 
12858  status = db_paste(hDB, hKeyTmp, init_str);
12859  if (status != DB_SUCCESS) {
12861  return status;
12862  }
12863 
12864  buffer_size = 10000;
12865  buffer = (char *) malloc(buffer_size);
12866  do {
12867  size = buffer_size;
12868  status = db_copy(hDB, hKeyOrig, buffer, &size, "");
12869  if (status == DB_TRUNCATED) {
12870  buffer_size += 10000;
12871  buffer = (char *) realloc(buffer, buffer_size);
12872  continue;
12873  }
12874  if (status != DB_SUCCESS) {
12876  return status;
12877  }
12878 
12879  } while (status != DB_SUCCESS);
12880 
12881  status = db_paste(hDB, hKeyTmpO, buffer);
12882  if (status != DB_SUCCESS) {
12883  free(buffer);
12885  return status;
12886  }
12887 
12888  /* merge temporay record and original record */
12889  db_scan_tree_link(hDB, hKeyTmpO, 0, merge_records, NULL);
12890 
12891  /* delete original record */
12892  while (1) {
12893  db_enum_link(hDB, hKeyOrig, 0, &hSubkey);
12894  if (!hSubkey)
12895  break;
12896 
12898  if (status != DB_SUCCESS) {
12899  free(buffer);
12901  return status;
12902  }
12903  }
12904 
12905  /* copy merged record to original record */
12906  do {
12907  size = buffer_size;
12908  status = db_copy(hDB, hKeyTmp, buffer, &size, "");
12909  if (status == DB_TRUNCATED) {
12910  buffer_size += 10000;
12911  buffer = (char *) realloc(buffer, buffer_size);
12912  continue;
12913  }
12914  if (status != DB_SUCCESS) {
12915  free(buffer);
12917  return status;
12918  }
12919 
12920  } while (status != DB_SUCCESS);
12921 
12922  status = db_paste(hDB, hKeyOrig, buffer);
12923  if (status != DB_SUCCESS) {
12924  free(buffer);
12926  return status;
12927  }
12928 
12929  /* delete temporary records */
12930  db_delete_key(hDB, hKeyTmp, FALSE);
12931  db_delete_key(hDB, hKeyTmpO, FALSE);
12932 
12933  free(buffer);
12934  buffer = NULL;
12935  } else if (status == DB_NO_KEY) {
12936  /* create fresh record */
12937  db_create_key(hDB, hKey, key_name, TID_KEY);
12938  status = db_find_key(hDB, hKey, key_name, &hKeyTmp);
12939  if (status != DB_SUCCESS) {
12941  return status;
12942  }
12943 
12944  status = db_paste(hDB, hKeyTmp, init_str);
12945  if (status != DB_SUCCESS) {
12947  return status;
12948  }
12949  } else {
12950  cm_msg(MERROR, "db_create_record", "aborting on unexpected failure of db_find_key(%s), status %d", key_name, status);
12951  abort();
12952  }
12953 
12955 
12956  return DB_SUCCESS;
12957 }
#define DB_OPEN_RECORD
Definition: midas.h:656
std::string ss_tid_to_string(midas_thread_t thread_id)
Definition: system.cxx:1542
midas_thread_t ss_gettid(void)
Definition: system.cxx:1490
static void check_open_keys(HNDLE hDB, HNDLE hKey, KEY *pkey, INT level, void *info)
Definition: odb.cxx:12737
INT db_delete_key(HNDLE hDB, HNDLE hKey, BOOL follow_links)
Definition: odb.cxx:3846
INT db_create_key(HNDLE hDB, HNDLE hKey, const char *key_name, DWORD type)
Definition: odb.cxx:3298
INT db_scan_tree_link(HNDLE hDB, HNDLE hKey, INT level, void(*callback)(HNDLE, HNDLE, KEY *, INT, void *), void *info)
Definition: odb.cxx:4836
INT db_paste(HNDLE hDB, HNDLE hKeyRoot, const char *buffer)
Definition: odb.cxx:8487
static void merge_records(HNDLE hDB, HNDLE hKey, KEY *pkey, INT level, void *info)
Definition: odb.cxx:12663
#define RPC_DB_CREATE_RECORD
Definition: mrpc.h:80
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_delete_client_info()

INT EXPRT db_delete_client_info ( HNDLE  hDB,
int  pid 
)

Delete client info from database

Parameters
hDBDatabase handle
pidPID of entry to delete, zero for this process.
Returns
CM_SUCCESS

Definition at line 2781 of file odb.cxx.

2782 {
2783 #ifdef LOCAL_ROUTINES
2784  if (hDB > _database_entries || hDB <= 0) {
2785  cm_msg(MERROR, "db_delete_client_info", "invalid database handle");
2786  return DB_INVALID_HANDLE;
2787  }
2788 
2789  if (!_database[hDB - 1].attached) {
2790  cm_msg(MERROR, "db_delete_client_info", "invalid database handle");
2791  return DB_INVALID_HANDLE;
2792  }
2793 
2794  /* lock database */
2796 
2797  DATABASE *pdb = &_database[hDB - 1];
2798  DATABASE_HEADER *pheader = pdb->database_header;
2799 
2800  db_allow_write_locked(pdb, "db_delete_client_info");
2801 
2802  db_err_msg* msg = NULL;
2803 
2804  int status = db_delete_client_info_wlocked(hDB, pheader, pid, &msg);
2805 
2807 
2808  if (msg)
2809  db_flush_msg(&msg);
2810 
2811  return status;
2812 #else
2813  return DB_SUCCESS;
2814 #endif
2815 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_delete_client_info_wlocked()

static int db_delete_client_info_wlocked ( HNDLE  hDB,
DATABASE_HEADER pheader,
int  pid,
db_err_msg **  msg 
)
static

Definition at line 2750 of file odb.cxx.

2751 {
2752  if (!pid)
2753  pid = ss_getpid();
2754 
2755  char str[256];
2756  int status = 0;
2757 
2758  sprintf(str, "System/Clients/%0d", pid);
2759  KEY* pkey = (KEY*)db_find_pkey_locked(pheader, NULL, str, &status, msg);
2760  if (!pkey) {
2761  return status;
2762  }
2763 
2764  status = db_set_mode_wlocked(pheader, pkey, MODE_READ | MODE_WRITE | MODE_DELETE, 2, msg);
2765  HNDLE hKey = db_pkey_to_hkey(pheader, pkey);
2766  status = db_delete_key1(hDB, hKey, 1, TRUE);
2767  int32_t data = 0;
2768  db_set_value_wlocked(pheader, hDB, 0, "/System/Client Notify", &data, sizeof(data), 1, TID_INT32, msg);
2769 
2770  return status;
2771 }
#define TID_INT32
Definition: midas.h:346
INT ss_getpid(void)
Definition: system.cxx:1383
INT db_delete_key1(HNDLE hDB, HNDLE hKey, INT level, BOOL follow_links)
Definition: odb.cxx:3659
static int db_set_mode_wlocked(DATABASE_HEADER *, KEY *, WORD mode, int recurse, db_err_msg **)
Definition: odb.cxx:7973
static int db_set_value_wlocked(DATABASE_HEADER *pheader, HNDLE hDB, KEY *pkey_root, const char *key_name, const void *data, INT data_size, INT num_values, DWORD type, db_err_msg **msg)
Definition: odb.cxx:5290
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_delete_client_wlocked()

static void db_delete_client_wlocked ( DATABASE_HEADER pheader,
int  jclient,
db_err_msg **  msg 
)
static

Definition at line 2715 of file odb.cxx.

2716 {
2717  DATABASE_CLIENT* pdbclient = &pheader->client[jclient];
2718 
2719  /* decrement notify_count for open records and clear exclusive mode */
2720  int k;
2721  for (k = 0; k < pdbclient->max_index; k++)
2722  if (pdbclient->open_record[k].handle) {
2723  KEY* pkey = (KEY *) ((char *) pheader + pdbclient->open_record[k].handle);
2724  if (pkey->notify_count > 0)
2725  pkey->notify_count--;
2726 
2727  if (pdbclient->open_record[k].access_mode & MODE_WRITE)
2728  db_set_mode_wlocked(pheader, pkey, (WORD) (pkey->access_mode & ~MODE_EXCLUSIVE), 2, msg);
2729  }
2730 
2731  /* clear entry from client structure in buffer header */
2732  memset(pdbclient, 0, sizeof(DATABASE_CLIENT));
2733 
2734  /* calculate new max_client_index entry */
2735  for (k = MAX_CLIENTS - 1; k >= 0; k--)
2736  if (pheader->client[k].pid != 0)
2737  break;
2738  pheader->max_client_index = k + 1;
2739 
2740  /* count new number of clients */
2741  int nc;
2742  for (k = MAX_CLIENTS - 1, nc = 0; k >= 0; k--)
2743  if (pheader->client[k].pid != 0)
2744  nc++;
2745  pheader->num_clients = nc;
2746 }
INT k
Definition: odbhist.cxx:40
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_delete_key()

INT EXPRT db_delete_key ( HNDLE  hDB,
HNDLE  hKey,
BOOL  follow_links 
)

Delete a subtree in a database starting from a key (including this key).

...
status = db_find_link(hDB, 0, str, &hkey);
{
cm_msg(MINFO,"my_delete"," "Cannot find key %s", str);
return;
}
status = db_delete_key(hDB, hkey, FALSE);
if (status != DB_SUCCESS)
{
cm_msg(MERROR,"my_delete"," "Cannot delete key %s", str);
return;
}
...
Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyfor key where search starts, zero for root.
follow_linksFollow links when TRUE.
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_NO_ACCESS, DB_OPEN_RECORD

Definition at line 3846 of file odb.cxx.

3847 {
3848  if (rpc_is_remote())
3849  return rpc_call(RPC_DB_DELETE_KEY, hDB, hKey, follow_links);
3850 
3851  return db_delete_key1(hDB, hKey, 0, follow_links);
3852 }
#define RPC_DB_DELETE_KEY
Definition: mrpc.h:62
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_delete_key1()

INT db_delete_key1 ( HNDLE  hDB,
HNDLE  hKey,
INT  level,
BOOL  follow_links 
)

Delete a subtree, using level information (only called internally by db_delete_key())

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyKey handle to start with, 0 for root
levelRecursion level, must be zero when
follow_linksFollow links when TRUE called from a user routine
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_OPEN_RECORD

Definition at line 3659 of file odb.cxx.

3660 {
3661 #ifdef LOCAL_ROUTINES
3662  {
3663  DATABASE_HEADER *pheader;
3664  KEYLIST *pkeylist;
3665  KEY *pkey, *pnext_key, *pkey_tmp;
3666  HNDLE hKeyLink;
3667  BOOL deny_delete;
3668  INT status;
3669  BOOL locked = FALSE;
3670 
3671  if (hDB > _database_entries || hDB <= 0) {
3672  cm_msg(MERROR, "db_delete_key1", "invalid database handle");
3673  return DB_INVALID_HANDLE;
3674  }
3675 
3676  if (!_database[hDB - 1].attached) {
3677  cm_msg(MERROR, "db_delete_key1", "invalid database handle");
3678  return DB_INVALID_HANDLE;
3679  }
3680 
3681  if (hKey < (int) sizeof(DATABASE_HEADER)) {
3682  cm_msg(MERROR, "db_delete_key1", "invalid key handle");
3683  return DB_INVALID_HANDLE;
3684  }
3685 
3686  /* lock database at the top level */
3687  if (level == 0) {
3689  locked = TRUE;
3690  }
3691 
3692  pheader = _database[hDB - 1].database_header;
3693 
3694  /* check if hKey argument is correct */
3695  if (!db_validate_hkey(pheader, hKey)) {
3696  if (locked)
3698  return DB_INVALID_HANDLE;
3699  }
3700 
3701  pkey = (KEY *) ((char *) pheader + hKey);
3702 
3703  /* check if someone has opened key or parent */
3704  if (level == 0)
3705  do {
3706 #ifdef CHECK_OPEN_RECORD
3707  if (pkey->notify_count) {
3708  if (locked)
3710  return DB_OPEN_RECORD;
3711  }
3712 #endif
3713  if (pkey->parent_keylist == 0)
3714  break;
3715 
3716  pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
3717  // FIXME: validate pkeylist->parent
3718  pkey = (KEY *) ((char *) pheader + pkeylist->parent);
3719  } while (TRUE);
3720 
3721  pkey = (KEY *) ((char *) pheader + hKey);
3722  pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
3723 
3724  deny_delete = FALSE;
3725 
3726  /* first recures subtree for keys */
3727  if (pkey->type == TID_KEY && pkeylist->first_key) {
3728  pkey = (KEY *) ((char *) pheader + pkeylist->first_key);
3729 
3730  do {
3731  pnext_key = (KEY *) (POINTER_T) pkey->next_key; // FIXME: what is this casting of hKey to pointer?
3732 
3733  status = db_delete_key1(hDB, (POINTER_T) pkey - (POINTER_T) pheader, level + 1, follow_links);
3734 
3735  if (status == DB_NO_ACCESS)
3736  deny_delete = TRUE;
3737 
3738  if (pnext_key) {
3739  // FIXME: validate pnext_key
3740  pkey = (KEY *) ((char *) pheader + (POINTER_T) pnext_key);
3741  }
3742  } while (pnext_key);
3743  }
3744 
3745  /* follow links if requested */
3746  if (pkey->type == TID_LINK && follow_links) {
3747  status = db_find_key1(hDB, 0, (char *) pheader + pkey->data, &hKeyLink);
3748  if (status == DB_SUCCESS && follow_links < 100)
3749  db_delete_key1(hDB, hKeyLink, level + 1, follow_links + 1);
3750 
3751  if (follow_links == 100)
3752  cm_msg(MERROR, "db_delete_key1", "try to delete cyclic link");
3753  }
3754 
3755  /* check if hKey argument is correct */
3756  if (!db_validate_hkey(pheader, hKey)) {
3757  if (locked)
3759  return DB_INVALID_HANDLE;
3760  }
3761 
3762  pkey = (KEY *) ((char *) pheader + hKey);
3763 
3764  /* return if key was already deleted by cyclic link */
3765  if (pkey->parent_keylist == 0) {
3766  if (locked)
3768  return DB_SUCCESS;
3769  }
3770 
3771  /* now delete key */
3772  if (hKey != pheader->root_key) {
3773  if (!(pkey->access_mode & MODE_DELETE) || deny_delete) {
3774  if (locked)
3776  return DB_NO_ACCESS;
3777  }
3778 #ifdef CHECK_OPEN_RECORD
3779  if (pkey->notify_count) {
3780  if (locked)
3782  return DB_OPEN_RECORD;
3783  }
3784 #endif
3785  db_allow_write_locked(&_database[hDB - 1], "db_delete_key1");
3786 
3787  /* delete key data */
3788  if (pkey->type == TID_KEY)
3789  free_key(pheader, (char *) pheader + pkey->data, pkey->total_size);
3790  else
3791  free_data(pheader, (char *) pheader + pkey->data, pkey->total_size, "db_delete_key1");
3792 
3793  /* unlink key from list */
3794  pnext_key = (KEY *) (POINTER_T) pkey->next_key;
3795  pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
3796 
3797  if ((KEY *) ((char *) pheader + pkeylist->first_key) == pkey) {
3798  /* key is first in list */
3799  pkeylist->first_key = (POINTER_T) pnext_key;
3800  } else {
3801  /* find predecessor */
3802  pkey_tmp = (KEY *) ((char *) pheader + pkeylist->first_key);
3803  while ((KEY *) ((char *) pheader + pkey_tmp->next_key) != pkey)
3804  pkey_tmp = (KEY *) ((char *) pheader + pkey_tmp->next_key);
3805  pkey_tmp->next_key = (POINTER_T) pnext_key;
3806  }
3807 
3808  /* delete key */
3809  free_key(pheader, pkey, sizeof(KEY));
3810  pkeylist->num_keys--;
3811  }
3812 
3813  if (locked)
3815  }
3816 #endif /* LOCAL_ROUTINES */
3817 
3818  return DB_SUCCESS;
3819 }
static void free_key(DATABASE_HEADER *pheader, void *address, INT size)
Definition: odb.cxx:280
INT db_find_key1(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
Definition: odb.cxx:4115
static bool db_validate_hkey(const DATABASE_HEADER *pheader, HNDLE hKey)
Definition: odb.cxx:920
static int free_data(DATABASE_HEADER *pheader, void *address, INT size, const char *caller)
Definition: odb.cxx:451
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_enum_first_locked()

static const KEY* db_enum_first_locked ( const DATABASE_HEADER pheader,
const KEY pkey,
db_err_msg **  msg 
)
static

Definition at line 1059 of file odb.cxx.

1060 {
1061  HNDLE hKey = db_pkey_to_hkey(pheader, pkey);
1062 
1063  if (pkey->type != TID_KEY) {
1064  std::string path = db_get_path_locked(pheader, hKey);
1065  db_msg(msg, MERROR, "db_enum_first_locked", "hkey %d path \"%s\" tid %d is not a directory", hKey, path.c_str(), pkey->type);
1066  return NULL;
1067  }
1068 
1069  const KEYLIST *pkeylist = db_get_pkeylist(pheader, hKey, pkey, "db_find_key", msg);
1070 
1071  if (!pkeylist) {
1072  // error
1073  return NULL;
1074  }
1075 
1076  if (pkeylist->num_keys == 0) {
1077  // empty directory
1078  return NULL;
1079  }
1080 
1081  if (pkeylist->first_key == 0) {
1082  // empty directory
1083  return NULL;
1084  }
1085 
1086  return db_get_pkey(pheader, pkeylist->first_key, NULL, "db_enum_first_locked", msg);
1087 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_enum_key()

INT EXPRT db_enum_key ( HNDLE  hDB,
HNDLE  hKey,
INT  idx,
HNDLE subkey_handle 
)

Enumerate subkeys from a key, follow links.

hkey must correspond to a valid ODB directory. The index is usually incremented in a loop until the last key is reached. Information about the sub-keys can be obtained with db_get_key(). If a returned key is of type TID_KEY, it contains itself sub-keys. To scan a whole ODB sub-tree, the function db_scan_tree() can be used.

HNDLE hkey, hsubkey;
db_find_key(hdb, 0, "/Runinfo", &hkey);
for (i=0 ; ; i++)
{
db_enum_key(hdb, hkey, i, &hsubkey);
if (!hSubkey)
break; // end of list reached
// print key name
db_get_key(hdb, hkey, &key);
printf("%s\n", key.name);
}
INT db_enum_key(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
Definition: odb.cxx:5576
HNDLE hdb
Definition: midas_macro.h:21
Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
idxSubkey index, sould be initially 0, then incremented in each call until subhKey becomes zero and the function returns DB_NO_MORE_SUBKEYS
subkey_handleHandle of subkey which can be used in db_get_key() and db_get_data()
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_NO_MORE_SUBKEYS

Definition at line 5576 of file odb.cxx.

5577 {
5578  if (rpc_is_remote())
5579  return rpc_call(RPC_DB_ENUM_KEY, hDB, hKey, idx, subkey_handle);
5580 
5581 #ifdef LOCAL_ROUTINES
5582  {
5583  DATABASE_HEADER *pheader;
5584  INT i;
5585  char str[256];
5586  HNDLE parent;
5587 
5588  if (hDB > _database_entries || hDB <= 0) {
5589  cm_msg(MERROR, "db_enum_key", "invalid database handle");
5590  return DB_INVALID_HANDLE;
5591  }
5592 
5593  if (!_database[hDB - 1].attached) {
5594  cm_msg(MERROR, "db_enum_key", "invalid database handle");
5595  return DB_INVALID_HANDLE;
5596  }
5597 
5598  *subkey_handle = 0;
5599 
5600  /* first lock database */
5602 
5603  pheader = _database[hDB - 1].database_header;
5604  if (!hKey)
5605  hKey = pheader->root_key;
5606 
5607  /* check if hKey argument is correct */
5608  if (!db_validate_hkey(pheader, hKey)) {
5610  return DB_INVALID_HANDLE;
5611  }
5612 
5613  db_err_msg *msg = NULL;
5614  int status;
5615 
5616  const KEY* pkey = db_get_pkey(pheader, hKey, &status, "db_enum_key", &msg);
5617 
5618  if (!pkey) {
5620  db_flush_msg(&msg);
5621  return DB_NO_MORE_SUBKEYS;
5622  }
5623 
5624  if (pkey->type != TID_KEY) {
5626  return DB_NO_MORE_SUBKEYS;
5627  }
5628 
5629  const KEYLIST* pkeylist = db_get_pkeylist(pheader, hKey, pkey, "db_enum_key", &msg);
5630 
5631  if (!pkeylist) {
5633  db_flush_msg(&msg);
5634  return DB_NO_MORE_SUBKEYS;
5635  }
5636 
5637  if (idx >= pkeylist->num_keys) {
5639  return DB_NO_MORE_SUBKEYS;
5640  }
5641 
5642  pkey = db_get_pkey(pheader, pkeylist->first_key, &status, "db_enum_key", &msg);
5643 
5644  if (!pkey) {
5645  std::string path = db_get_path_locked(pheader, hKey);
5646  HNDLE xfirst_key = pkeylist->first_key;
5648  if (msg)
5649  db_flush_msg(&msg);
5650  cm_msg(MERROR, "db_enum_key", "hkey %d path \"%s\" invalid first_key %d", hKey, path.c_str(), xfirst_key);
5651  return DB_NO_MORE_SUBKEYS;
5652  }
5653 
5654  for (i = 0; i < idx; i++) {
5655  if (pkey->next_key == 0) {
5656  std::string path = db_get_path_locked(pheader, hKey);
5658  cm_msg(MERROR, "db_enum_key", "hkey %d path \"%s\" unexpected end of key list at index %d", hKey, path.c_str(), i);
5659  return DB_NO_MORE_SUBKEYS;
5660  }
5661 
5662  pkey = db_get_pkey(pheader, pkey->next_key, &status, "db_enum_key", &msg);
5663 
5664  if (!pkey) {
5665  std::string path = db_get_path_locked(pheader, hKey);
5667  db_flush_msg(&msg);
5668  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);
5669  return DB_NO_MORE_SUBKEYS;
5670  }
5671  }
5672 
5673  /* resolve links */
5674  if (pkey->type == TID_LINK) {
5675  strcpy(str, (char *) pheader + pkey->data);
5676 
5677  /* no not resolve if link to array index */
5678  if (strlen(str) > 0 && str[strlen(str) - 1] == ']') {
5679  *subkey_handle = (POINTER_T) pkey - (POINTER_T) pheader;
5681  return DB_SUCCESS;
5682  }
5683 
5684  if (*str == '/') {
5685  /* absolute path */
5687  return db_find_key(hDB, 0, str, subkey_handle);
5688  } else {
5689  /* relative path */
5690  if (pkey->parent_keylist) {
5691  pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
5692  parent = pkeylist->parent;
5694  return db_find_key(hDB, parent, str, subkey_handle);
5695  } else {
5697  return db_find_key(hDB, 0, str, subkey_handle);
5698  }
5699  }
5700  }
5701 
5702  *subkey_handle = (POINTER_T) pkey - (POINTER_T) pheader;
5704  }
5705 #endif /* LOCAL_ROUTINES */
5706 
5707  return DB_SUCCESS;
5708 }
#define DB_NO_MORE_SUBKEYS
Definition: midas.h:652
#define RPC_DB_ENUM_KEY
Definition: mrpc.h:63
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_enum_link()

INT EXPRT db_enum_link ( HNDLE  hDB,
HNDLE  hKey,
INT  idx,
HNDLE subkey_handle 
)

dox

Definition at line 5715 of file odb.cxx.

5741 {
5742  if (rpc_is_remote())
5743  return rpc_call(RPC_DB_ENUM_LINK, hDB, hKey, idx, subkey_handle);
5744 
5745 #ifdef LOCAL_ROUTINES
5746  {
5747  DATABASE_HEADER *pheader;
5748  KEYLIST *pkeylist;
5749  KEY *pkey;
5750  INT i;
5751 
5752  if (hDB > _database_entries || hDB <= 0) {
5753  cm_msg(MERROR, "db_enum_link", "invalid database handle");
5754  return DB_INVALID_HANDLE;
5755  }
5756 
5757  if (!_database[hDB - 1].attached) {
5758  cm_msg(MERROR, "db_enum_link", "invalid database handle");
5759  return DB_INVALID_HANDLE;
5760  }
5761 
5762  *subkey_handle = 0;
5763 
5764  /* first lock database */
5766 
5767  pheader = _database[hDB - 1].database_header;
5768  if (!hKey)
5769  hKey = pheader->root_key;
5770 
5771  /* check if hKey argument is correct */
5772  if (!db_validate_hkey(pheader, hKey)) {
5774  return DB_INVALID_HANDLE;
5775  }
5776 
5777  pkey = (KEY *) ((char *) pheader + hKey);
5778 
5779  if (pkey->type != TID_KEY) {
5781  return DB_NO_MORE_SUBKEYS;
5782  }
5783  pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
5784 
5785  if (idx >= pkeylist->num_keys) {
5787  return DB_NO_MORE_SUBKEYS;
5788  }
5789 
5790  // FIXME: validate pkeylist->first_key
5791  pkey = (KEY *) ((char *) pheader + pkeylist->first_key);
5792  for (i = 0; i < idx; i++) {
5793  // FIXME: validate pkey->next_key
5794  pkey = (KEY *) ((char *) pheader + pkey->next_key);
5795  }
5796 
5797  *subkey_handle = (POINTER_T) pkey - (POINTER_T) pheader;
5799  }
5800 #endif /* LOCAL_ROUTINES */
5801 
5802  return DB_SUCCESS;
5803 }
#define RPC_DB_ENUM_LINK
Definition: mrpc.h:78
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_enum_next_locked()

static const KEY* db_enum_next_locked ( const DATABASE_HEADER pheader,
const KEY pdir,
const KEY pkey,
db_err_msg **  msg 
)
static

Definition at line 1089 of file odb.cxx.

1090 {
1091  if (pkey->next_key == 0)
1092  return NULL;
1093 
1094  return db_get_pkey(pheader, pkey->next_key, NULL, "db_enum_next_locked", msg);
1095 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_find_key()

INT EXPRT db_find_key ( HNDLE  hDB,
HNDLE  hKey,
const char *  key_name,
HNDLE subhKey 
)

Returns key handle for a key with a specific name.

Keys can be accessed by their name including the directory or by a handle. A key handle is an internal offset to the shared memory where the ODB lives and allows a much faster access to a key than via its name.

The function db_find_key() must be used to convert a key name to a handle. Most other database functions use this key handle in various operations.

HNDLE hkey, hsubkey;
// use full name, start from root
db_find_key(hDB, 0, "/Runinfo/Run number", &hkey);
// start from subdirectory
db_find_key(hDB, 0, "/Runinfo", &hkey);
db_find_key(hdb, hkey, "Run number", &hsubkey);
Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
key_nameName of key to search, can contain directories.
subhKeyReturned handle of key, zero if key cannot be found.
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_NO_ACCESS, DB_NO_KEY

Definition at line 4069 of file odb.cxx.

4070 {
4071  if (rpc_is_remote())
4072  return rpc_call(RPC_DB_FIND_KEY, hDB, hKey, key_name, subhKey);
4073 
4074 #ifdef LOCAL_ROUTINES
4075  {
4076  DATABASE_HEADER *pheader;
4077  INT status;
4078 
4079  *subhKey = 0;
4080 
4081  if (hDB > _database_entries || hDB <= 0) {
4082  cm_msg(MERROR, "db_find_key", "invalid database handle");
4083  return DB_INVALID_HANDLE;
4084  }
4085 
4086  if (!_database[hDB - 1].attached) {
4087  cm_msg(MERROR, "db_find_key", "invalid database handle");
4088  return DB_INVALID_HANDLE;
4089  }
4090 
4091  db_err_msg *msg = NULL;
4092 
4094 
4095  pheader = _database[hDB - 1].database_header;
4096 
4097  status = db_find_key_locked(pheader, hKey, key_name, subhKey, &msg);
4098 
4100 
4101  if (msg)
4102  db_flush_msg(&msg);
4103 
4104  return status;
4105  }
4106 #endif /* LOCAL_ROUTINES */
4107 
4108  return DB_SUCCESS;
4109 }
static INT db_find_key_locked(const DATABASE_HEADER *pheader, HNDLE hKey, const char *key_name, HNDLE *subhKey, db_err_msg **msg)
Definition: odb.cxx:4021
#define RPC_DB_FIND_KEY
Definition: mrpc.h:59
Here is the call graph for this function:

◆ db_find_key1()

INT EXPRT db_find_key1 ( HNDLE  hDB,
HNDLE  hKey,
const char *  key_name,
HNDLE subhKey 
)

dox

Definition at line 4115 of file odb.cxx.

4137 {
4138  if (rpc_is_remote())
4139  return rpc_call(RPC_DB_FIND_KEY, hDB, hKey, key_name, subhKey);
4140 
4141 #ifdef LOCAL_ROUTINES
4142  {
4143  DATABASE_HEADER *pheader;
4144  KEYLIST *pkeylist;
4145  KEY *pkey;
4146  const char *pkey_name;
4147  INT i;
4148 
4149  *subhKey = 0;
4150 
4151  if (hDB > _database_entries || hDB <= 0) {
4152  cm_msg(MERROR, "db_find_key", "invalid database handle");
4153  return DB_INVALID_HANDLE;
4154  }
4155 
4156  if (!_database[hDB - 1].attached) {
4157  cm_msg(MERROR, "db_find_key", "invalid database handle");
4158  return DB_INVALID_HANDLE;
4159  }
4160 
4161  pheader = _database[hDB - 1].database_header;
4162  if (!hKey)
4163  hKey = pheader->root_key;
4164 
4165  /* check if hKey argument is correct */
4166  if (!db_validate_hkey(pheader, hKey)) {
4167  return DB_INVALID_HANDLE;
4168  }
4169 
4170  pkey = (KEY *) ((char *) pheader + hKey);
4171 
4172  if (pkey->type != TID_KEY) {
4173  cm_msg(MERROR, "db_find_key", "key has no subkeys");
4174  *subhKey = 0;
4175  return DB_NO_KEY;
4176  }
4177  pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
4178 
4179  if (key_name[0] == 0 || strcmp(key_name, "/") == 0) {
4180  if (!(pkey->access_mode & MODE_READ)) {
4181  *subhKey = 0;
4182  return DB_NO_ACCESS;
4183  }
4184 
4185  *subhKey = (POINTER_T) pkey - (POINTER_T) pheader;
4186 
4187  return DB_SUCCESS;
4188  }
4189 
4190  pkey_name = key_name;
4191  do {
4192  char str[MAX_ODB_PATH];
4193 
4194  /* extract single subkey from key_name */
4195  pkey_name = extract_key(pkey_name, str, sizeof(str));
4196 
4197  /* check if parent or current directory */
4198  if (strcmp(str, "..") == 0) {
4199  if (pkey->parent_keylist) {
4200  pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
4201  // FIXME: validate pkeylist->parent
4202  pkey = (KEY *) ((char *) pheader + pkeylist->parent);
4203  }
4204  continue;
4205  }
4206  if (strcmp(str, ".") == 0)
4207  continue;
4208 
4209  /* check if key is in keylist */
4210  // FIXME: validate pkeylist->first_key
4211  pkey = (KEY *) ((char *) pheader + pkeylist->first_key);
4212 
4213  for (i = 0; i < pkeylist->num_keys; i++) {
4214  if (equal_ustring(str, pkey->name))
4215  break;
4216 
4217  // FIXME: validate pkey->next_key
4218  pkey = (KEY *) ((char *) pheader + pkey->next_key);
4219  }
4220 
4221  if (i == pkeylist->num_keys) {
4222  *subhKey = 0;
4223  return DB_NO_KEY;
4224  }
4225 
4226  /* resolve links */
4227  if (pkey->type == TID_LINK) {
4228  /* copy destination, strip '/' */
4229  strcpy(str, (char *) pheader + pkey->data);
4230  if (str[strlen(str) - 1] == '/')
4231  str[strlen(str) - 1] = 0;
4232 
4233  /* append rest of key name if existing */
4234  if (pkey_name[0]) {
4235  strcat(str, pkey_name);
4236  return db_find_key1(hDB, 0, str, subhKey);
4237  } else {
4238  /* if last key in chain is a link, return its destination */
4239  return db_find_link1(hDB, 0, str, subhKey);
4240  }
4241  }
4242 
4243  /* key found: check if last in chain */
4244  if (*pkey_name == '/') {
4245  if (pkey->type != TID_KEY) {
4246  *subhKey = 0;
4247  return DB_NO_KEY;
4248  }
4249  }
4250 
4251  /* descend one level */
4252  pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
4253 
4254  } while (*pkey_name == '/' && *(pkey_name + 1));
4255 
4256  *subhKey = (POINTER_T) pkey - (POINTER_T) pheader;
4257  }
4258 #endif /* LOCAL_ROUTINES */
4259 
4260  return DB_SUCCESS;
4261 }
INT db_find_link1(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
Definition: odb.cxx:4429
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_find_key_locked()

static int db_find_key_locked ( const DATABASE_HEADER pheader,
HNDLE  hKey,
const char *  key_name,
HNDLE subhKey,
db_err_msg **  msg 
)
static

Definition at line 4021 of file odb.cxx.

4022 {
4023  int status;
4024  const KEY* pkey = db_get_pkey(pheader, hKey, &status, "db_find_key", msg);
4025  if (!pkey) {
4026  if (subhKey)
4027  *subhKey = 0;
4028  return status;
4029  }
4030 
4031  const KEY* plink = db_find_pkey_locked(pheader, pkey, key_name, &status, msg);
4032 
4033  if (!plink) {
4034  *subhKey = 0;
4035  return status;
4036  }
4037 
4038  *subhKey = db_pkey_to_hkey(pheader, plink);
4039 
4040  return DB_SUCCESS;
4041 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_find_keys()

INT EXPRT db_find_keys ( HNDLE  hDB,
HNDLE  hKeyRoot,
char *  odbpath,
std::vector< HNDLE > &  hKeyVector 
)

Definition at line 4576 of file odb.cxx.

4599 {
4600  HNDLE hKey, hSubKey=0;
4601  KEY key;
4602  INT status;
4603  char *pattern = NULL;
4604  char *subkeypath = NULL;
4605  char *parentkeypath = NULL;
4606  char localpath[256];
4607 
4608  //make work on a local copy od odbpath to allow recursion
4609  strcpy(localpath, odbpath);
4610  parentkeypath = localpath;
4611 
4612  char *wildcard = strpbrk(localpath, "*?");
4613  if(wildcard){
4614  //wildcard found
4615  subkeypath = strchr(wildcard, '/');
4616  if(subkeypath){
4617  //truncate the string at slash
4618  *subkeypath = 0;
4619  subkeypath++;
4620  }
4621  parentkeypath = strrchr(localpath, '/');
4622  if(parentkeypath){
4623  //truncate there too
4624  *parentkeypath = 0;
4625  pattern = parentkeypath+1;
4626  if((parentkeypath-1) == localpath){
4627  //path starts with '/', no parent path
4628  parentkeypath = NULL;
4629  } else {
4630  parentkeypath = localpath;
4631  }
4632  } else {
4633  //wildcard at top level, start with pattern
4634  pattern = localpath;
4635  parentkeypath = NULL;
4636  }
4637  }
4638 
4639  //if available search for parent key path
4640  if(parentkeypath){
4641  status = db_find_key(hDB, hKeyRoot, parentkeypath, &hKey);
4642  if (status != DB_SUCCESS)
4643  return status;
4644  } else {
4645  hKey = hKeyRoot;
4646  }
4647 
4648  //if a pattern is found
4649  if(pattern){
4650  //try match all subkeys
4651  status = DB_NO_KEY;
4652  for (int i=0 ; ; i++)
4653  {
4654  db_enum_key(hDB, hKey, i, &hSubKey);
4655  if (!hSubKey)
4656  break; // end of list reached
4657  db_get_key(hDB, hSubKey, &key);
4658 
4659  if(strmatch(pattern, key.name)){
4660  //match
4661  if(!subkeypath){
4662  //found
4663  hKeyVector.push_back(hSubKey);
4664 
4665  } else if (key.type == TID_KEY){
4666  //recurse with hSubKey as root key and subkeypath as path
4667  int subkeystatus = db_find_keys(hDB, hSubKey, subkeypath, hKeyVector);
4668  if (subkeystatus != DB_NO_KEY)
4669  status = subkeystatus;
4670 
4671  if (status != DB_SUCCESS && status != DB_NO_KEY)
4672  break;
4673  }
4674  }
4675  }
4676 
4677  return status;
4678  } else {
4679  //no pattern: hKey matches!
4680  db_get_key(hDB, hKey, &key);
4681  hKeyVector.push_back(hKey);
4682 
4683  return DB_SUCCESS;
4684  }
4685 
4686 }
BOOL strmatch(char *pattern, char *str)
Definition: odb.cxx:3225
INT db_find_keys(HNDLE hDB, HNDLE hKeyRoot, char *odbpath, std::vector< HNDLE > &hKeyVector)
Definition: odb.cxx:4576
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_find_link()

INT EXPRT db_find_link ( HNDLE  hDB,
HNDLE  hKey,
const char *  key_name,
HNDLE subhKey 
)

Definition at line 4264 of file odb.cxx.

4290 {
4291  if (rpc_is_remote())
4292  return rpc_call(RPC_DB_FIND_LINK, hDB, hKey, key_name, subhKey);
4293 
4294 #ifdef LOCAL_ROUTINES
4295  {
4296  DATABASE_HEADER *pheader;
4297  KEYLIST *pkeylist;
4298  KEY *pkey;
4299  const char *pkey_name;
4300  INT i;
4301 
4302  *subhKey = 0;
4303 
4304  if (hDB > _database_entries || hDB <= 0) {
4305  cm_msg(MERROR, "db_find_link", "Invalid database handle");
4306  return DB_INVALID_HANDLE;
4307  }
4308 
4309  if (!_database[hDB - 1].attached) {
4310  cm_msg(MERROR, "db_find_link", "invalid database handle");
4311  return DB_INVALID_HANDLE;
4312  }
4313 
4315 
4316  pheader = _database[hDB - 1].database_header;
4317  if (!hKey)
4318  hKey = pheader->root_key;
4319 
4320  /* check if hKey argument is correct */
4321  if (!db_validate_hkey(pheader, hKey)) {
4323  return DB_INVALID_HANDLE;
4324  }
4325 
4326  pkey = (KEY *) ((char *) pheader + hKey);
4327 
4328  if (pkey->type != TID_KEY) {
4330  cm_msg(MERROR, "db_find_link", "key has no subkeys");
4331  return DB_NO_KEY;
4332  }
4333  pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
4334 
4335  if (key_name[0] == 0 || strcmp(key_name, "/") == 0) {
4336  if (!(pkey->access_mode & MODE_READ)) {
4337  *subhKey = 0;
4339  return DB_NO_ACCESS;
4340  }
4341 
4342  *subhKey = (POINTER_T) pkey - (POINTER_T) pheader;
4343 
4345  return DB_SUCCESS;
4346  }
4347 
4348  pkey_name = key_name;
4349  do {
4350  char str[MAX_ODB_PATH];
4351 
4352  /* extract single subkey from key_name */
4353  pkey_name = extract_key(pkey_name, str, sizeof(str));
4354 
4355  /* check if parent or current directory */
4356  if (strcmp(str, "..") == 0) {
4357  if (pkey->parent_keylist) {
4358  pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
4359  // FIXME: validate pkeylist->parent
4360  pkey = (KEY *) ((char *) pheader + pkeylist->parent);
4361  }
4362  continue;
4363  }
4364  if (strcmp(str, ".") == 0)
4365  continue;
4366 
4367  /* check if key is in keylist */
4368  // FIXME: validate pkeylist->first_key
4369  pkey = (KEY *) ((char *) pheader + pkeylist->first_key);
4370 
4371  for (i = 0; i < pkeylist->num_keys; i++) {
4372  if (!db_validate_key_offset(pheader, pkey->next_key)) {
4373  int pkey_next_key = pkey->next_key;
4375  cm_msg(MERROR, "db_find_link", "Warning: database corruption, key \"%s\", next_key 0x%08X is invalid", key_name, pkey_next_key - (int)sizeof(DATABASE_HEADER));
4376  *subhKey = 0;
4377  return DB_CORRUPTED;
4378  }
4379 
4380  if (equal_ustring(str, pkey->name))
4381  break;
4382 
4383  pkey = (KEY *) ((char *) pheader + pkey->next_key); // FIXME: pkey->next_key could be zero
4384  }
4385 
4386  if (i == pkeylist->num_keys) {
4387  *subhKey = 0;
4389  return DB_NO_KEY;
4390  }
4391 
4392  /* resolve links if not last in chain */
4393  if (pkey->type == TID_LINK && *pkey_name == '/') {
4394  /* copy destination, strip '/' */
4395  strcpy(str, (char *) pheader + pkey->data);
4396  if (str[strlen(str) - 1] == '/')
4397  str[strlen(str) - 1] = 0;
4398 
4399  /* append rest of key name */
4400  strcat(str, pkey_name);
4402  return db_find_link(hDB, 0, str, subhKey);
4403  }
4404 
4405  /* key found: check if last in chain */
4406  if ((*pkey_name == '/')) {
4407  if (pkey->type != TID_KEY) {
4408  *subhKey = 0;
4410  return DB_NO_KEY;
4411  }
4412  }
4413 
4414  /* descend one level */
4415  pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
4416 
4417  } while (*pkey_name == '/' && *(pkey_name + 1));
4418 
4419  *subhKey = (POINTER_T) pkey - (POINTER_T) pheader;
4420 
4422  }
4423 #endif /* LOCAL_ROUTINES */
4424 
4425  return DB_SUCCESS;
4426 }
static bool db_validate_key_offset(const DATABASE_HEADER *pheader, int offset)
Definition: odb.cxx:896
#define RPC_DB_FIND_LINK
Definition: mrpc.h:60
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_find_link1()

INT EXPRT db_find_link1 ( HNDLE  hDB,
HNDLE  hKey,
const char *  key_name,
HNDLE subhKey 
)

Definition at line 4429 of file odb.cxx.

4451 {
4452  if (rpc_is_remote())
4453  return rpc_call(RPC_DB_FIND_LINK, hDB, hKey, key_name, subhKey);
4454 
4455 #ifdef LOCAL_ROUTINES
4456  {
4457  DATABASE_HEADER *pheader;
4458  KEYLIST *pkeylist;
4459  KEY *pkey;
4460  const char *pkey_name;
4461  INT i;
4462 
4463  *subhKey = 0;
4464 
4465  if (hDB > _database_entries || hDB <= 0) {
4466  cm_msg(MERROR, "db_find_link", "Invalid database handle");
4467  return DB_INVALID_HANDLE;
4468  }
4469 
4470  if (!_database[hDB - 1].attached) {
4471  cm_msg(MERROR, "db_find_link", "invalid database handle");
4472  return DB_INVALID_HANDLE;
4473  }
4474 
4475  pheader = _database[hDB - 1].database_header;
4476  if (!hKey)
4477  hKey = pheader->root_key;
4478 
4479  /* check if hKey argument is correct */
4480  if (!db_validate_hkey(pheader, hKey)) {
4481  return DB_INVALID_HANDLE;
4482  }
4483 
4484  pkey = (KEY *) ((char *) pheader + hKey);
4485 
4486  if (pkey->type != TID_KEY) {
4487  cm_msg(MERROR, "db_find_link", "key has no subkeys");
4488  return DB_NO_KEY;
4489  }
4490  pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
4491 
4492  if (key_name[0] == 0 || strcmp(key_name, "/") == 0) {
4493  if (!(pkey->access_mode & MODE_READ)) {
4494  *subhKey = 0;
4495  return DB_NO_ACCESS;
4496  }
4497 
4498  *subhKey = (POINTER_T) pkey - (POINTER_T) pheader;
4499 
4500  return DB_SUCCESS;
4501  }
4502 
4503  pkey_name = key_name;
4504  do {
4505  char str[MAX_ODB_PATH];
4506  /* extract single subkey from key_name */
4507  pkey_name = extract_key(pkey_name, str, sizeof(str));
4508 
4509  /* check if parent or current directory */
4510  if (strcmp(str, "..") == 0) {
4511  if (pkey->parent_keylist) {
4512  pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
4513  // FIXME: validate pkeylist->parent
4514  pkey = (KEY *) ((char *) pheader + pkeylist->parent);
4515  }
4516  continue;
4517  }
4518  if (strcmp(str, ".") == 0)
4519  continue;
4520 
4521  /* check if key is in keylist */
4522  // FIXME: validate pkeylist->first_key
4523  pkey = (KEY *) ((char *) pheader + pkeylist->first_key);
4524 
4525  for (i = 0; i < pkeylist->num_keys; i++) {
4526  if (!db_validate_key_offset(pheader, pkey->next_key)) {
4527  cm_msg(MERROR, "db_find_link1", "Warning: database corruption, key \"%s\", next_key 0x%08X is invalid", key_name, pkey->next_key - (int)sizeof(DATABASE_HEADER));
4528  *subhKey = 0;
4529  return DB_CORRUPTED;
4530  }
4531 
4532  if (equal_ustring(str, pkey->name))
4533  break;
4534 
4535  pkey = (KEY *) ((char *) pheader + pkey->next_key); // FIXME: pkey->next_key could be zero
4536  }
4537 
4538  if (i == pkeylist->num_keys) {
4539  *subhKey = 0;
4540  return DB_NO_KEY;
4541  }
4542 
4543  /* resolve links if not last in chain */
4544  if (pkey->type == TID_LINK && *pkey_name == '/') {
4545  /* copy destination, strip '/' */
4546  strcpy(str, (char *) pheader + pkey->data);
4547  if (str[strlen(str) - 1] == '/')
4548  str[strlen(str) - 1] = 0;
4549 
4550  /* append rest of key name */
4551  strcat(str, pkey_name);
4552  return db_find_link1(hDB, 0, str, subhKey);
4553  }
4554 
4555  /* key found: check if last in chain */
4556  if ((*pkey_name == '/')) {
4557  if (pkey->type != TID_KEY) {
4558  *subhKey = 0;
4559  return DB_NO_KEY;
4560  }
4561  }
4562 
4563  /* descend one level */
4564  pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
4565 
4566  } while (*pkey_name == '/' && *(pkey_name + 1));
4567 
4568  *subhKey = (POINTER_T) pkey - (POINTER_T) pheader;
4569  }
4570 #endif /* LOCAL_ROUTINES */
4571 
4572  return DB_SUCCESS;
4573 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_find_open_records()

static int db_find_open_records ( HNDLE  hDB,
HNDLE  hKey,
KEY key,
INT  level,
void *  xresult 
)
static

Definition at line 5094 of file odb.cxx.

5095 {
5096  /* check if this key has notify count set */
5097  if (key->notify_count) {
5098 
5100 
5101  DATABASE_HEADER *pheader = _database[hDB - 1].database_header;
5102 
5103  std::string path = db_get_path_locked(pheader, hKey);
5104 
5105  std::string line = msprintf("%s open %d times by", path.c_str(), key->notify_count);
5106 
5107  //printf("path [%s] key.name [%s]\n", path, key->name);
5108 
5109  int count = 0;
5110  for (int i = 0; i < pheader->max_client_index; i++) {
5111  DATABASE_CLIENT *pclient = &pheader->client[i];
5112  for (int j = 0; j < pclient->max_index; j++)
5113  if (pclient->open_record[j].handle == hKey) {
5114  count++;
5115  line += " \"";
5116  line += pclient->name;
5117  line += "\"";
5118  //sprintf(line + strlen(line), ", handle %d, mode %d ", pclient->open_record[j].handle, pclient->open_record[j].access_mode);
5119  }
5120  }
5121 
5122  if (count < 1) {
5123  line += " a deleted client";
5124  }
5125 
5126  line += "\n";
5127 
5128  std::string *result = (std::string*)xresult;
5129  *result = line;
5130 
5132  }
5133  return DB_SUCCESS;
5134 }
double count
Definition: mdump.cxx:36
std::string msprintf(const char *format,...)
Definition: midas.cxx:412
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_find_pkey_locked()

static const KEY * db_find_pkey_locked ( const DATABASE_HEADER pheader,
const KEY pkey,
const char *  key_name,
int *  pstatus,
db_err_msg **  msg 
)
static

Definition at line 3855 of file odb.cxx.

3856 {
3857  if (pkey == NULL) {
3858  pkey = db_get_pkey(pheader, pheader->root_key, pstatus, "db_find_key", msg);
3859  if (!pkey) {
3860  return NULL;
3861  }
3862  }
3863 
3864  HNDLE hKey = db_pkey_to_hkey(pheader, pkey);
3865 
3866  if (pkey->type != TID_KEY) {
3867  DWORD tid = pkey->type;
3868  std::string path = db_get_path_locked(pheader, hKey);
3869  db_msg(msg, MERROR, "db_find_key", "hkey %d path \"%s\" tid %d is not a directory, looking for \"%s\"", hKey, path.c_str(), tid, key_name);
3870  if (pstatus)
3871  *pstatus = DB_NO_KEY;
3872  return NULL;
3873  }
3874 
3875  if (key_name[0] == 0 || strcmp(key_name, "/") == 0) {
3876  if (!(pkey->access_mode & MODE_READ)) {
3877  if (pstatus)
3878  *pstatus = DB_NO_ACCESS;
3879  return NULL;
3880  }
3881  return pkey;
3882  }
3883 
3884  const KEYLIST *pkeylist = db_get_pkeylist(pheader, hKey, pkey, "db_find_key", msg);
3885  if (!pkeylist) {
3886  if (pstatus)
3887  *pstatus = DB_CORRUPTED;
3888  return NULL;
3889  }
3890 
3891  HNDLE last_good_hkey = hKey;
3892 
3893  const char *pkey_name = key_name;
3894  do {
3895  assert(pkeylist!=NULL); // should never happen!
3896 
3897  char str[MAX_ODB_PATH];
3898 
3899  /* extract single subkey from key_name */
3900  pkey_name = extract_key(pkey_name, str, sizeof(str));
3901 
3902  /* strip trailing '[n]' */
3903  if (strchr(str, '[') && str[strlen(str) - 1] == ']')
3904  *strchr(str, '[') = 0;
3905 
3906  /* check if parent or current directory */
3907  if (strcmp(str, "..") == 0) {
3908  if (pkey->parent_keylist) {
3909  pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
3910  // FIXME: validate pkeylist->parent
3911  pkey = (KEY *) ((char *) pheader + pkeylist->parent);
3912  }
3913  continue;
3914  }
3915  if (strcmp(str, ".") == 0)
3916  continue;
3917 
3918  last_good_hkey = hKey;
3919 
3920  hKey = pkeylist->first_key;
3921 
3922  if (hKey == 0) {
3923  // empty subdirectory
3924  if (pstatus)
3925  *pstatus = DB_NO_KEY;
3926  return NULL;
3927  }
3928 
3929  int i;
3930  for (i = 0; i < pkeylist->num_keys; i++) {
3931  pkey = db_get_pkey(pheader, hKey, pstatus, "db_find_key", msg);
3932 
3933  if (!pkey) {
3934  std::string path = db_get_path_locked(pheader, last_good_hkey);
3935  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);
3936  return NULL;
3937  }
3938 
3939  if (!db_validate_key_offset(pheader, pkey->next_key)) {
3940  std::string path = db_get_path_locked(pheader, hKey);
3941  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);
3942  if (pstatus)
3943  *pstatus = DB_CORRUPTED;
3944  return NULL;
3945  }
3946 
3947  if (equal_ustring(str, pkey->name))
3948  break;
3949 
3950  if (pkey->next_key == 0) {
3951  if (pstatus)
3952  *pstatus = DB_NO_KEY;
3953  return NULL;
3954  }
3955 
3956  hKey = pkey->next_key;
3957  }
3958 
3959  if (i == pkeylist->num_keys) {
3960  if (pstatus)
3961  *pstatus = DB_NO_KEY;
3962  return NULL;
3963  }
3964 
3965  /* resolve links */
3966  if (pkey->type == TID_LINK) {
3967  /* copy destination, strip '/' */
3968  strlcpy(str, (char *) pheader + pkey->data, sizeof(str));
3969  if (str[strlen(str) - 1] == '/')
3970  str[strlen(str) - 1] = 0;
3971 
3972  /* if link is pointer to array index, return link instead of destination */
3973  if (str[strlen(str) - 1] == ']')
3974  break;
3975 
3976  /* append rest of key name if existing */
3977  if (pkey_name[0]) {
3978  strlcat(str, pkey_name, sizeof(str));
3979  return db_find_pkey_locked(pheader, NULL, str, pstatus, msg);
3980  } else {
3981  /* if last key in chain is a link, return its destination */
3982  int status = 0;
3983  const KEY *plink = db_find_pkey_locked(pheader, NULL, str, &status, msg);
3984  if (pstatus) {
3985  if (status == DB_NO_KEY)
3986  *pstatus = DB_INVALID_LINK;
3987  else
3988  *pstatus = status;
3989  }
3990  return plink;
3991  }
3992  }
3993 
3994  /* key found: check if last in chain */
3995  if (*pkey_name == '/') {
3996  if (pkey->type != TID_KEY) {
3997  if (pstatus)
3998  *pstatus = DB_NO_KEY;
3999  return NULL;
4000  }
4001  }
4002 
4003  if (pkey->type == TID_KEY) {
4004  /* descend one level */
4005  pkeylist = db_get_pkeylist(pheader, hKey, pkey, "db_find_key", msg);
4006 
4007  if (!pkeylist) {
4008  if (pstatus)
4009  *pstatus = DB_CORRUPTED;
4010  return NULL;
4011  }
4012  } else {
4013  pkeylist = NULL;
4014  }
4015 
4016  } while (*pkey_name == '/' && *(pkey_name + 1));
4017 
4018  return pkey;
4019 }
#define DB_INVALID_LINK
Definition: midas.h:658
size_t EXPRT strlcat(char *dst, const char *src, size_t size)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_fix_open_records()

static int db_fix_open_records ( HNDLE  hDB,
HNDLE  hKey,
KEY key,
INT  level,
void *  xresult 
)
static

Definition at line 5136 of file odb.cxx.

5137 {
5138  std::string *result = (std::string*)xresult;
5139 
5140  /* check if this key has notify count set */
5141  if (key->notify_count) {
5143  DATABASE_HEADER *pheader = _database[hDB - 1].database_header;
5144  db_allow_write_locked(&_database[hDB - 1], "db_fix_open_records");
5145 
5146  int i;
5147  for (i = 0; i < pheader->max_client_index; i++) {
5148  DATABASE_CLIENT *pclient = &pheader->client[i];
5149  int j;
5150  for (j = 0; j < pclient->max_index; j++)
5151  if (pclient->open_record[j].handle == hKey)
5152  break;
5153  if (j < pclient->max_index)
5154  break;
5155  }
5156  if (i == pheader->max_client_index) {
5157  /* check if hKey argument is correct */
5158  if (!db_validate_hkey(pheader, hKey)) {
5160  return DB_SUCCESS;
5161  }
5162 
5163  /* reset notify count */
5164  KEY *pkey = (KEY *) ((char *) pheader + hKey);
5165  pkey->notify_count = 0;
5166 
5167  std::string path = db_get_path_locked(pheader, hKey);
5168  *result += path;
5169  *result += " fixed\n";
5170  }
5171 
5173  }
5174  return DB_SUCCESS;
5175 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_flush_database()

INT db_flush_database ( HNDLE  hDB)

dox

Definition at line 2259 of file odb.cxx.

2279 {
2280  if (rpc_is_remote())
2282 
2283 #ifdef LOCAL_ROUTINES
2284  else {
2285  int status, size;
2286  uint32_t flush_period = 60;
2287  uint32_t last_flush = 0;
2288 
2289  if (hDB > _database_entries || hDB <= 0) {
2290  cm_msg(MERROR, "db_flush_database", "invalid database handle");
2291  return DB_INVALID_HANDLE;
2292  }
2293 
2294  /* create keys if not present */
2295  size = sizeof(flush_period);
2296  db_get_value(hDB, 0, "/System/Flush/Flush period", &flush_period, &size, TID_UINT32, true);
2297  size = sizeof(last_flush);
2298  db_get_value(hDB, 0, "/System/Flush/Last flush", &last_flush, &size, TID_UINT32, true);
2299 
2300  HNDLE hkey;
2301  status = db_find_key(hDB, 0, "/System/Flush/Last flush", &hkey);
2302  if (status != DB_SUCCESS) {
2303  cm_msg(MERROR, "db_flush_database", "Cannot obtain key /System/Flush/Last flush");
2304  return DB_INVALID_HANDLE;
2305  }
2306 
2308  DATABASE *pdb = &_database[hDB - 1];
2309  DATABASE_HEADER *pheader = pdb->database_header;
2310 
2311  if (!_database[hDB - 1].attached) {
2313  cm_msg(MERROR, "db_flush_database", "invalid database handle");
2314  return DB_INVALID_HANDLE;
2315  }
2316 
2317  db_err_msg *msg = nullptr;
2318 
2319  const KEY *pkey = db_get_pkey(pheader, hkey, &status, "db_flush_database", &msg);
2320 
2321  if (!pkey) {
2323  if (msg)
2324  db_flush_msg(&msg);
2325  return CM_NO_CLIENT;
2326  }
2327 
2328  size = sizeof(last_flush);
2329  status = db_get_data_locked(pheader, pkey, 0, &last_flush, &size, TID_UINT32, &msg);
2330 
2331  /* only flush if period has expired */
2332  if (ss_time() > last_flush + flush_period) {
2333  db_allow_write_locked(pdb, "db_flush_database");
2334 
2335  /* update last flush time in ODB */
2336  last_flush = ss_time();
2337  db_set_value_wlocked(pheader, hDB, 0, "/System/Flush/Last flush", &last_flush, sizeof(last_flush), 1, TID_UINT32, &msg);
2338 
2339  /* flush shared memory to disk */
2340  ss_shm_flush(pheader->name, _database[hDB - 1].shm_adr, _database[hDB - 1].shm_size, _database[hDB - 1].shm_handle, false);
2341  }
2342 
2344  }
2345 #endif /* LOCAL_ROUTINES */
2346 
2347  return DB_SUCCESS;
2348 }
#define TID_UINT32
Definition: midas.h:344
DWORD ss_time()
Definition: system.cxx:3401
INT db_get_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, void *data, INT *buf_size, DWORD type, BOOL create)
Definition: odb.cxx:5405
#define RPC_DB_FLUSH_DATABASE
Definition: mrpc.h:84
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_flush_msg()

void db_flush_msg ( db_err_msg **  msg)
static

Definition at line 170 of file odb.cxx.

171 {
172  db_err_msg *msg = *msgp;
173  *msgp = NULL;
174 
175  if (/* DISABLES CODE */ (0)) {
176  printf("db_flush_msg: %p\n", msg);
177  db_print_msg(msg);
178  }
179 
180  while (msg != NULL) {
181  cm_msg(msg->message_type, msg->filename.c_str(), msg->line, msg->routine.c_str(), "%s", msg->text.c_str());
182  db_err_msg* next = msg->next;
183  msg->message_type = 0;
184  msg->next = NULL;
185  delete msg;
186  msg = next;
187  }
188 }
static void static void db_print_msg(const db_err_msg *msg)
Definition: odb.cxx:116
int message_type
Definition: odb.cxx:107
std::string routine
Definition: odb.cxx:110
std::string filename
Definition: odb.cxx:108
std::string text
Definition: odb.cxx:111
db_err_msg * next
Definition: odb.cxx:106
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_data()

INT EXPRT db_get_data ( HNDLE  hDB,
HNDLE  hKey,
void *  data,
INT buf_size,
DWORD  type 
)

dox Get key data from a handle

The function returns single values or whole arrays which are contained in an ODB key. Since the data buffer is of type void, no type checking can be performed by the compiler. Therefore the type has to be explicitly supplied, which is checked against the type stored in the ODB.

HNLDE hkey;
// get key handle for run number
db_find_key(hDB, 0, "/Runinfo/Run number", &hkey);
// return run number
size = sizeof(run_number);
INT run_number[2]
Definition: mana.cxx:246
Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
dataPointer to the return data.
buf_sizeSize of data buffer.
typeType of key, one of TID_xxx (see Midas_Data_Types).
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_TRUNCATED, DB_TYPE_MISMATCH

Definition at line 6529 of file odb.cxx.

6530 {
6531  if (rpc_is_remote())
6532  return rpc_call(RPC_DB_GET_DATA, hDB, hKey, data, buf_size, type);
6533 
6534 #ifdef LOCAL_ROUTINES
6535  {
6536  int status;
6537 
6538  if (hDB > _database_entries || hDB <= 0) {
6539  cm_msg(MERROR, "db_get_data", "Invalid database handle");
6540  return DB_INVALID_HANDLE;
6541  }
6542 
6543  if (!_database[hDB - 1].attached) {
6544  cm_msg(MERROR, "db_get_data", "invalid database handle");
6545  return DB_INVALID_HANDLE;
6546  }
6547 
6548  if (hKey < (int) sizeof(DATABASE_HEADER)) {
6549  cm_msg(MERROR, "db_get_data", "invalid key handle");
6550  return DB_INVALID_HANDLE;
6551  }
6552 
6554 
6555  DATABASE_HEADER* pheader = _database[hDB - 1].database_header;
6556  db_err_msg* msg = NULL;
6557 
6558  const KEY* pkey = db_get_pkey(pheader, hKey, &status, "db_get_data", &msg);
6559 
6560  if (!pkey) {
6562  if (msg)
6563  db_flush_msg(&msg);
6564  return status;
6565  }
6566 
6567  /* check for read access */
6568  if (!(pkey->access_mode & MODE_READ)) {
6570  if (msg)
6571  db_flush_msg(&msg);
6572  return DB_NO_ACCESS;
6573  }
6574 
6575  /* follow links to array index */
6576  if (pkey->type == TID_LINK) {
6577  std::string link_name = (char *) pheader + pkey->data;
6578  if (link_name.length() > 0 && link_name.back() == ']') {
6579  size_t pos = link_name.rfind("[");
6580  if (pos == std::string::npos) {
6581  db_msg(&msg, MERROR, "db_get_data", "missing \"[\" in symlink to array element \"%s\" in \"%s\"", link_name.c_str(), db_get_path_locked(pheader, pkey).c_str());
6583  if (msg)
6584  db_flush_msg(&msg);
6585  return DB_INVALID_LINK;
6586  }
6587  int idx = atoi(link_name.c_str()+pos+1);
6588  link_name.resize(pos);
6589  //printf("link name [%s] idx %d\n", link_name.c_str(), idx);
6590 
6591  // relative symlinks did not work in the old db_get_data(), make sure they do not work now. K.O.
6592  if (link_name[0] != '/') {
6593  db_msg(&msg, MERROR, "db_get_data", "symlink \"%s\" should start with \"/\" in \"%s\"", link_name.c_str(), db_get_path_locked(pheader, pkey).c_str());
6595  if (msg)
6596  db_flush_msg(&msg);
6597  return DB_INVALID_LINK;
6598  }
6599 
6600  const KEY* pkey = db_find_pkey_locked(pheader, NULL, link_name.c_str(), &status, &msg);
6601 
6602  if (!pkey) {
6604  if (msg)
6605  db_flush_msg(&msg);
6606  return status;
6607  }
6608 
6609  //printf("db_get_data [%s] type [%s] idx %d\n", db_get_path_locked(pheader, pkey).c_str(), rpc_tid_name(type), idx);
6610 
6611  status = db_get_data_locked(pheader, pkey, idx, data, buf_size, type, &msg);
6612 
6614  if (msg)
6615  db_flush_msg(&msg);
6616  return status;
6617  }
6618  }
6619 
6620  //printf("db_get_data [%s] type [%s]\n", db_get_path_locked(pheader, pkey).c_str(), rpc_tid_name(type));
6621 
6622  status = db_get_data_locked(pheader, pkey, -1, data, buf_size, type, &msg);
6623 
6625  if (msg)
6626  db_flush_msg(&msg);
6627 
6628  return status;
6629  }
6630 #endif /* LOCAL_ROUTINES */
6631 
6632  return DB_SUCCESS;
6633 }
#define RPC_DB_GET_DATA
Definition: mrpc.h:65
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_data1()

INT EXPRT db_get_data1 ( HNDLE  hDB,
HNDLE  hKey,
void *  data,
INT buf_size,
DWORD  type,
INT num_values 
)

dox

Definition at line 6747 of file odb.cxx.

6772 {
6773  if (rpc_is_remote())
6774  return rpc_call(RPC_DB_GET_DATA1, hDB, hKey, data, buf_size, type, num_values);
6775 
6776 #ifdef LOCAL_ROUTINES
6777  {
6778  DATABASE_HEADER *pheader;
6779  KEY *pkey;
6780 
6781  if (hDB > _database_entries || hDB <= 0) {
6782  cm_msg(MERROR, "db_get_data", "Invalid database handle");
6783  return DB_INVALID_HANDLE;
6784  }
6785 
6786  if (!_database[hDB - 1].attached) {
6787  cm_msg(MERROR, "db_get_data", "invalid database handle");
6788  return DB_INVALID_HANDLE;
6789  }
6790 
6791  if (hKey < (int) sizeof(DATABASE_HEADER)) {
6792  cm_msg(MERROR, "db_get_data", "invalid key handle");
6793  return DB_INVALID_HANDLE;
6794  }
6795 
6797 
6798  pheader = _database[hDB - 1].database_header;
6799 
6800  /* check if hKey argument is correct */
6801  if (!db_validate_hkey(pheader, hKey)) {
6803  return DB_INVALID_HANDLE;
6804  }
6805 
6806  pkey = (KEY *) ((char *) pheader + hKey);
6807 
6808  /* check for read access */
6809  if (!(pkey->access_mode & MODE_READ)) {
6811  return DB_NO_ACCESS;
6812  }
6813 
6814  if (!pkey->type) {
6815  int pkey_type = pkey->type;
6817  cm_msg(MERROR, "db_get_data", "hkey %d invalid key type %d", hKey, pkey_type);
6818  return DB_INVALID_HANDLE;
6819  }
6820 
6821  if (pkey->type != type) {
6822  int pkey_type = pkey->type;
6823  char pkey_name[NAME_LENGTH];
6824  strlcpy(pkey_name, pkey->name, sizeof(pkey_name));
6826  cm_msg(MERROR, "db_get_data", "\"%s\" is of type %s, not %s", pkey_name, rpc_tid_name(pkey_type), rpc_tid_name(type));
6827  return DB_TYPE_MISMATCH;
6828  }
6829 
6830  /* keys cannot contain data */
6831  if (pkey->type == TID_KEY) {
6833  cm_msg(MERROR, "db_get_data", "Key cannot contain data");
6834  return DB_TYPE_MISMATCH;
6835  }
6836 
6837  /* check if key has data */
6838  if (pkey->data == 0) {
6839  memset(data, 0, *buf_size);
6840  *buf_size = 0;
6842  return DB_SUCCESS;
6843  }
6844 
6845  /* check if buffer is too small */
6846  if (pkey->num_values * pkey->item_size > *buf_size) {
6847  int pkey_size = pkey->num_values * pkey->item_size;
6848  memcpy(data, (char *) pheader + pkey->data, *buf_size);
6850  char str[MAX_ODB_PATH];
6851  db_get_path(hDB, hKey, str, sizeof(str));
6852  cm_msg(MERROR, "db_get_data", "data for key \"%s\" truncated from %d to %d bytes", str, pkey_size, *buf_size);
6853  return DB_TRUNCATED;
6854  }
6855 
6856  /* copy key data */
6857  memcpy(data, (char *) pheader + pkey->data, pkey->num_values * pkey->item_size);
6858  *buf_size = pkey->num_values * pkey->item_size;
6859  *num_values = pkey->num_values;
6860 
6862 
6863  }
6864 #endif /* LOCAL_ROUTINES */
6865 
6866  return DB_SUCCESS;
6867 }
#define RPC_DB_GET_DATA1
Definition: mrpc.h:87
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_data_index()

INT EXPRT db_get_data_index ( HNDLE  hDB,
HNDLE  hKey,
void *  data,
INT buf_size,
INT  idx,
DWORD  type 
)

dox returns a single value of keys containing arrays of values.

The function returns a single value of keys containing arrays of values.

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
dataSize of data buffer.
buf_sizeReturn size of the record.
idxIndex of array [0..n-1].
typeType of key, one of TID_xxx (see Midas_Data_Types).
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_TRUNCATED, DB_OUT_OF_RANGE

Definition at line 6885 of file odb.cxx.

6886 {
6887  if (rpc_is_remote())
6888  return rpc_call(RPC_DB_GET_DATA_INDEX, hDB, hKey, data, buf_size, idx, type);
6889 
6890 #ifdef LOCAL_ROUTINES
6891  {
6892  DATABASE_HEADER *pheader;
6893  KEY *pkey;
6894  char str[256];
6895 
6896  if (hDB > _database_entries || hDB <= 0) {
6897  cm_msg(MERROR, "db_get_data", "Invalid database handle");
6898  return DB_INVALID_HANDLE;
6899  }
6900 
6901  if (!_database[hDB - 1].attached) {
6902  cm_msg(MERROR, "db_get_data", "invalid database handle");
6903  return DB_INVALID_HANDLE;
6904  }
6905 
6906  if (hKey < (int) sizeof(DATABASE_HEADER)) {
6907  cm_msg(MERROR, "db_get_data", "invalid key handle");
6908  return DB_INVALID_HANDLE;
6909  }
6910 
6912 
6913  pheader = _database[hDB - 1].database_header;
6914 
6915  /* check if hKey argument is correct */
6916  if (!db_validate_hkey(pheader, hKey)) {
6918  return DB_INVALID_HANDLE;
6919  }
6920 
6921  pkey = (KEY *) ((char *) pheader + hKey);
6922 
6923  /* check for read access */
6924  if (!(pkey->access_mode & MODE_READ)) {
6926  return DB_NO_ACCESS;
6927  }
6928 
6929  if (!pkey->type) {
6930  int pkey_type = pkey->type;
6932  cm_msg(MERROR, "db_get_data_index", "hkey %d invalid key type %d", hKey, pkey_type);
6933  return DB_INVALID_HANDLE;
6934  }
6935 
6936  if (pkey->type != type) {
6937  int pkey_type = pkey->type;
6938  char pkey_name[NAME_LENGTH];
6939  strlcpy(pkey_name, pkey->name, sizeof(pkey_name));
6941  cm_msg(MERROR, "db_get_data_index", "\"%s\" is of type %s, not %s", pkey_name, rpc_tid_name(pkey_type), rpc_tid_name(type));
6942  return DB_TYPE_MISMATCH;
6943  }
6944 
6945  /* keys cannot contain data */
6946  if (pkey->type == TID_KEY) {
6948  cm_msg(MERROR, "db_get_data_index", "Key cannot contain data");
6949  return DB_TYPE_MISMATCH;
6950  }
6951 
6952  /* check if key has data */
6953  if (pkey->data == 0) {
6954  memset(data, 0, *buf_size);
6955  *buf_size = 0;
6957  return DB_SUCCESS;
6958  }
6959 
6960  /* check if index in range */
6961  if (idx < 0 || idx >= pkey->num_values) {
6962  int pkey_num_values = pkey->num_values;
6963  memset(data, 0, *buf_size);
6965 
6966  db_get_path(hDB, hKey, str, sizeof(str));
6967  cm_msg(MERROR, "db_get_data_index", "index (%d) exceeds array length (%d) for key \"%s\"", idx, pkey_num_values, str);
6968  return DB_OUT_OF_RANGE;
6969  }
6970 
6971  /* check if buffer is too small */
6972  if (pkey->item_size > *buf_size) {
6973  int pkey_size = pkey->item_size;
6974  /* copy data */
6975  memcpy(data, (char *) pheader + pkey->data + idx * pkey->item_size, *buf_size);
6977  char str[MAX_ODB_PATH];
6978  db_get_path(hDB, hKey, str, sizeof(str));
6979  cm_msg(MERROR, "db_get_data_index", "data for key \"%s\" truncated from %d to %d bytes", str, pkey_size, *buf_size);
6980  return DB_TRUNCATED;
6981  }
6982 
6983  /* copy key data */
6984  memcpy(data, (char *) pheader + pkey->data + idx * pkey->item_size, pkey->item_size);
6985  *buf_size = pkey->item_size;
6986 
6988 
6989  }
6990 #endif /* LOCAL_ROUTINES */
6991 
6992  return DB_SUCCESS;
6993 }
#define DB_OUT_OF_RANGE
Definition: midas.h:657
#define RPC_DB_GET_DATA_INDEX
Definition: mrpc.h:81
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_data_locked()

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 
)
static

Definition at line 5496 of file odb.cxx.

5497 {
5498  /* check for correct type */
5499  if (pkey->type != (type)) {
5500  db_msg(msg, MERROR, "db_get_data_locked", "odb entry \"%s\" is of type %s, not %s", db_get_path_locked(pheader, pkey).c_str(), rpc_tid_name(pkey->type), rpc_tid_name(type));
5501  return DB_TYPE_MISMATCH;
5502  }
5503 
5504  /* check for correct type */
5505  if (pkey->type == TID_KEY) {
5506  db_msg(msg, MERROR, "db_get_data_locked", "odb entry \"%s\" is of type %s, cannot contain data", db_get_path_locked(pheader, pkey).c_str(), rpc_tid_name(pkey->type));
5507  return DB_TYPE_MISMATCH;
5508  }
5509 
5510  /* check for read access */
5511  if (!(pkey->access_mode & MODE_READ)) {
5512  db_msg(msg, MERROR, "db_get_data_locked", "odb entry \"%s\" has no read access", db_get_path_locked(pheader, pkey).c_str());
5513  return DB_NO_ACCESS;
5514  }
5515 
5516  /* check if buffer is too small */
5517  if ((idx == -1 && pkey->num_values * pkey->item_size > *buf_size) || (idx != -1 && pkey->item_size > *buf_size)) {
5518  memcpy(data, (char *) pheader + pkey->data, *buf_size);
5519  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_locked(pheader, pkey).c_str(), pkey->num_values * pkey->item_size, pkey->num_values, pkey->item_size, *buf_size);
5520  return DB_TRUNCATED;
5521  }
5522 
5523  /* check if index in boundaries */
5524  if (idx != -1 && idx >= pkey->num_values) {
5525  cm_msg(MERROR, "db_get_data_locked", "odb entry \"%s\" index %d is out of valid range 0..%d", db_get_path_locked(pheader, pkey).c_str(), idx, pkey->num_values-1);
5526  return DB_INVALID_PARAM;
5527  }
5528 
5529  /* copy key data */
5530  if (idx == -1) {
5531  memcpy(data, (char *) pheader + pkey->data, pkey->num_values * pkey->item_size);
5532  *buf_size = pkey->num_values * pkey->item_size;
5533  } else {
5534  memcpy(data, (char *) pheader + pkey->data + idx * pkey->item_size, pkey->item_size);
5535  *buf_size = pkey->item_size;
5536  }
5537 
5538  return DB_SUCCESS;
5539 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_free_mem()

INT db_get_free_mem ( HNDLE  hDB,
INT key_size,
INT data_size 
)

Definition at line 789 of file odb.cxx.

790 {
791  DATABASE_HEADER *pheader;
792  FREE_DESCRIP *pfree;
793 
794  *data_size = 0;
795  *key_size = 0;
796 
798 
799  pheader = _database[hDB - 1].database_header;
800 
801  pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_key);
802 
803  while ((POINTER_T) pfree != (POINTER_T) pheader) {
804  *key_size += pfree->size;
805  pfree = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
806  }
807 
808  *data_size = 0;
809  pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_data);
810 
811  while ((POINTER_T) pfree != (POINTER_T) pheader) {
812  *data_size += pfree->size;
813  pfree = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
814  }
815 
817  return DB_SUCCESS;
818 }
INT first_free_key
Definition: msystem.h:433
INT first_free_data
Definition: msystem.h:434
INT next_free
Definition: msystem.h:400
Here is the call graph for this function:

◆ db_get_key()

INT EXPRT db_get_key ( HNDLE  hDB,
HNDLE  hKey,
KEY key 
)

Get key structure from a handle.

KEY structure has following format:

typedef struct {
DWORD type; // TID_xxx type
INT num_values; // number of values
char name[NAME_LENGTH]; // name of variable
INT data; // Address of variable (offset)
INT total_size; // Total size of data block
INT item_size; // Size of single data item
WORD access_mode; // Access mode
WORD notify_count; // Notify counter
INT next_key; // Address of next key
INT parent_keylist; // keylist to which this key belongs
INT last_written; // Time of last write action
} KEY;

Most of these values are used for internal purposes, the values which are of public interest are type, name, num_values, item_size and total_size. For keys which contain a single value, num_values equals to one and total_size equals to item_size. For keys which contain an array of strings (TID_STRING), item_size equals to the length of one string.

HNDLE hkey;
db_find_key(hDB, 0, "/Runinfo/Run number", &hkey);
db_get_key(hDB, hkey, &key);
printf("The run number is of type %s\n", rpc_tid_name(key.type));
Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root. If Key is a link to an array element, this link is resolved. In this case function returns the key of the link destination and num_values is set to 1.
keyPointer to KEY stucture.
Returns
DB_SUCCESS, DB_INVALID_HANDLE

Definition at line 6009 of file odb.cxx.

6010 {
6011  if (rpc_is_remote())
6012  return rpc_call(RPC_DB_GET_KEY, hDB, hKey, key);
6013 
6014 #ifdef LOCAL_ROUTINES
6015  {
6016  DATABASE_HEADER *pheader;
6017  int status;
6018 
6019  if (hDB > _database_entries || hDB <= 0) {
6020  cm_msg(MERROR, "db_get_key", "invalid database handle");
6021  return DB_INVALID_HANDLE;
6022  }
6023 
6024  if (!_database[hDB - 1].attached) {
6025  cm_msg(MERROR, "db_get_key", "invalid database handle");
6026  return DB_INVALID_HANDLE;
6027  }
6028 
6029  if (hKey < (int) sizeof(DATABASE_HEADER) && hKey != 0) {
6030  cm_msg(MERROR, "db_get_key", "invalid key handle");
6031  return DB_INVALID_HANDLE;
6032  }
6033 
6034  db_err_msg *msg = NULL;
6035 
6037 
6038  pheader = _database[hDB - 1].database_header;
6039 
6040  status = db_get_key_locked(pheader, hKey, key, &msg);
6041 
6043 
6044  if (msg)
6045  db_flush_msg(&msg);
6046 
6047  return status;
6048  }
6049 #endif /* LOCAL_ROUTINES */
6050 
6051  return DB_SUCCESS;
6052 }
static INT db_get_key_locked(const DATABASE_HEADER *pheader, HNDLE hKey, KEY *key, db_err_msg **msg)
Definition: odb.cxx:5932
#define RPC_DB_GET_KEY
Definition: mrpc.h:64
Here is the call graph for this function:

◆ db_get_key_info()

INT EXPRT db_get_key_info ( HNDLE  hDB,
HNDLE  hKey,
char *  name,
INT  name_size,
INT type,
INT num_values,
INT item_size 
)

Get key info (separate values instead of structure)

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle of key to operate on
nameKey name
name_sizeSize of the give name (done with sizeof())
typeKey type (see Midas_Data_Types).
num_valuesNumber of values in key.
item_sizeSize of individual key value (used for strings)
Returns
DB_SUCCESS, DB_INVALID_HANDLE

Definition at line 6181 of file odb.cxx.

6182 {
6183  if (rpc_is_remote())
6184  return rpc_call(RPC_DB_GET_KEY_INFO, hDB, hKey, name, name_size, type, num_values, item_size);
6185 
6186 #ifdef LOCAL_ROUTINES
6187  {
6188  DATABASE_HEADER *pheader;
6189  KEY *pkey;
6190  KEYLIST *pkeylist;
6191 
6192  if (hDB > _database_entries || hDB <= 0) {
6193  cm_msg(MERROR, "db_get_key_info", "invalid database handle");
6194  return DB_INVALID_HANDLE;
6195  }
6196 
6197  if (!_database[hDB - 1].attached) {
6198  cm_msg(MERROR, "db_get_key_info", "invalid database handle");
6199  return DB_INVALID_HANDLE;
6200  }
6201 
6202  if (hKey < (int) sizeof(DATABASE_HEADER)) {
6203  cm_msg(MERROR, "db_get_key_info", "invalid key handle");
6204  return DB_INVALID_HANDLE;
6205  }
6206 
6208 
6209  pheader = _database[hDB - 1].database_header;
6210 
6211  /* check if hKey argument is correct */
6212  if (!db_validate_hkey(pheader, hKey)) {
6214  return DB_INVALID_HANDLE;
6215  }
6216 
6217  pkey = (KEY *) ((char *) pheader + hKey);
6218 
6219  if ((INT) strlen(pkey->name) + 1 > name_size) {
6220  /* truncate name */
6221  memcpy(name, pkey->name, name_size - 1);
6222  name[name_size] = 0;
6223  } else
6224  strcpy(name, pkey->name);
6225 
6226  /* convert "root" to "/" */
6227  if (strcmp(name, "root") == 0)
6228  strcpy(name, "/");
6229 
6230  *type = pkey->type;
6231  *num_values = pkey->num_values;
6232  *item_size = pkey->item_size;
6233 
6234  if (pkey->type == TID_KEY) {
6235  pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
6236  *num_values = pkeylist->num_keys;
6237  }
6238 
6240  }
6241 #endif /* LOCAL_ROUTINES */
6242 
6243  return DB_SUCCESS;
6244 }
#define RPC_DB_GET_KEY_INFO
Definition: mrpc.h:86
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_key_locked()

static INT db_get_key_locked ( const DATABASE_HEADER pheader,
HNDLE  hKey,
KEY key,
db_err_msg **  msg 
)
static

dox

Definition at line 5932 of file odb.cxx.

5933 {
5934  if (!hKey)
5935  hKey = pheader->root_key;
5936 
5937  /* check if hKey argument is correct */
5938  if (!db_validate_hkey(pheader, hKey)) {
5939  return DB_INVALID_HANDLE;
5940  }
5941 
5942  const KEY* pkey = (const KEY *) ((char *) pheader + hKey);
5943 
5944  if (pkey->type < 1 || pkey->type >= TID_LAST) {
5945  int pkey_type = pkey->type;
5946  db_msg(msg, MERROR, "db_get_key", "hkey %d invalid key type %d", hKey, pkey_type);
5947  return DB_INVALID_HANDLE;
5948  }
5949 
5950  /* check for link to array index */
5951  if (pkey->type == TID_LINK) {
5952  char link_name[MAX_ODB_PATH];
5953  strlcpy(link_name, (char *) pheader + pkey->data, sizeof(link_name));
5954  if (strlen(link_name) > 0 && link_name[strlen(link_name) - 1] == ']') {
5955  if (strchr(link_name, '[') == NULL)
5956  return DB_INVALID_LINK;
5957 
5958  HNDLE hkeylink;
5959  if (db_find_key_locked(pheader, 0, link_name, &hkeylink, msg) != DB_SUCCESS)
5960  return DB_INVALID_LINK;
5961  int status = db_get_key_locked(pheader, hkeylink, key, msg);
5962  key->num_values = 1; // fake number of values
5963  return status;
5964  }
5965  }
5966 
5967  memcpy(key, pkey, sizeof(KEY));
5968 
5969  return DB_SUCCESS;
5970 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_key_time()

INT EXPRT db_get_key_time ( HNDLE  hDB,
HNDLE  hKey,
DWORD delta 
)

Get time when key was last modified

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle of key to operate on
deltaSeconds since last update
Returns
DB_SUCCESS, DB_INVALID_HANDLE

Definition at line 6122 of file odb.cxx.

6123 {
6124  if (rpc_is_remote())
6125  return rpc_call(RPC_DB_GET_KEY_TIME, hDB, hKey, delta);
6126 
6127 #ifdef LOCAL_ROUTINES
6128  {
6129  DATABASE_HEADER *pheader;
6130  KEY *pkey;
6131 
6132  if (hDB > _database_entries || hDB <= 0) {
6133  cm_msg(MERROR, "db_get_key", "invalid database handle");
6134  return DB_INVALID_HANDLE;
6135  }
6136 
6137  if (!_database[hDB - 1].attached) {
6138  cm_msg(MERROR, "db_get_key", "invalid database handle");
6139  return DB_INVALID_HANDLE;
6140  }
6141 
6142  if (hKey < (int) sizeof(DATABASE_HEADER)) {
6143  cm_msg(MERROR, "db_get_key", "invalid key handle");
6144  return DB_INVALID_HANDLE;
6145  }
6146 
6148 
6149  pheader = _database[hDB - 1].database_header;
6150 
6151  /* check if hKey argument is correct */
6152  if (!db_validate_hkey(pheader, hKey)) {
6154  return DB_INVALID_HANDLE;
6155  }
6156 
6157  pkey = (KEY *) ((char *) pheader + hKey);
6158 
6159  *delta = ss_time() - pkey->last_written;
6160 
6162 
6163  }
6164 #endif /* LOCAL_ROUTINES */
6165 
6166  return DB_SUCCESS;
6167 }
#define RPC_DB_GET_KEY_TIME
Definition: mrpc.h:82
INT last_written
Definition: midas.h:1043
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_link()

INT EXPRT db_get_link ( HNDLE  hDB,
HNDLE  hKey,
KEY key 
)

Same as db_get_key, but it does not follow links

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
keyPointer to KEY stucture.
Returns
DB_SUCCESS, DB_INVALID_HANDLE

Definition at line 6062 of file odb.cxx.

6063 {
6064  if (rpc_is_remote())
6065  return rpc_call(RPC_DB_GET_LINK, hDB, hKey, key);
6066 
6067 #ifdef LOCAL_ROUTINES
6068  {
6069  DATABASE_HEADER *pheader;
6070 
6071  if (hDB > _database_entries || hDB <= 0) {
6072  cm_msg(MERROR, "db_get_link", "invalid database handle");
6073  return DB_INVALID_HANDLE;
6074  }
6075 
6076  if (!_database[hDB - 1].attached) {
6077  cm_msg(MERROR, "db_get_link", "invalid database handle");
6078  return DB_INVALID_HANDLE;
6079  }
6080 
6081  if (hKey < (int) sizeof(DATABASE_HEADER) && hKey != 0) {
6082  cm_msg(MERROR, "db_get_link", "invalid key handle");
6083  return DB_INVALID_HANDLE;
6084  }
6085 
6086  db_err_msg *msg = NULL;
6087 
6089 
6090  pheader = _database[hDB - 1].database_header;
6091 
6092  int status = DB_SUCCESS;
6093 
6094  const KEY* pkey = db_get_pkey(pheader, hKey, &status, "db_get_link", &msg);
6095  if (pkey) {
6096  memcpy(key, pkey, sizeof(KEY));
6097  } else {
6098  memset(key, 0, sizeof(KEY));
6099  //abort();
6100  }
6101 
6103 
6104  if (msg)
6105  db_flush_msg(&msg);
6106 
6107  return status;
6108  }
6109 #endif /* LOCAL_ROUTINES */
6110 
6111  return DB_SUCCESS;
6112 }
#define RPC_DB_GET_LINK
Definition: mrpc.h:91
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_link_data()

INT EXPRT db_get_link_data ( HNDLE  hDB,
HNDLE  hKey,
void *  data,
INT buf_size,
DWORD  type 
)

Same as db_get_data, but do not follow a link to an array index

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
dataPointer to the return data.
buf_sizeSize of data buffer.
typeType of key, one of TID_xxx (see Midas_Data_Types).
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_TRUNCATED, DB_TYPE_MISMATCH

Definition at line 6646 of file odb.cxx.

6647 {
6648  if (rpc_is_remote())
6649  return rpc_call(RPC_DB_GET_LINK_DATA, hDB, hKey, data, buf_size, type);
6650 
6651 #ifdef LOCAL_ROUTINES
6652  {
6653  DATABASE_HEADER *pheader;
6654  KEY *pkey;
6655 
6656  if (hDB > _database_entries || hDB <= 0) {
6657  cm_msg(MERROR, "db_get_data", "Invalid database handle");
6658  return DB_INVALID_HANDLE;
6659  }
6660 
6661  if (!_database[hDB - 1].attached) {
6662  cm_msg(MERROR, "db_get_data", "invalid database handle");
6663  return DB_INVALID_HANDLE;
6664  }
6665 
6666  if (hKey < (int) sizeof(DATABASE_HEADER)) {
6667  cm_msg(MERROR, "db_get_data", "invalid key handle");
6668  return DB_INVALID_HANDLE;
6669  }
6670 
6672 
6673  pheader = _database[hDB - 1].database_header;
6674 
6675  /* check if hKey argument is correct */
6676  if (!db_validate_hkey(pheader, hKey)) {
6678  return DB_INVALID_HANDLE;
6679  }
6680 
6681  pkey = (KEY *) ((char *) pheader + hKey);
6682 
6683  /* check for read access */
6684  if (!(pkey->access_mode & MODE_READ)) {
6686  return DB_NO_ACCESS;
6687  }
6688 
6689  if (!pkey->type) {
6690  int pkey_type = pkey->type;
6692  cm_msg(MERROR, "db_get_data", "hkey %d invalid key type %d", hKey, pkey_type);
6693  return DB_INVALID_HANDLE;
6694  }
6695 
6696  if (pkey->type != type) {
6697  int pkey_type = pkey->type;
6698  char pkey_name[NAME_LENGTH];
6699  strlcpy(pkey_name, pkey->name, sizeof(pkey_name));
6701  cm_msg(MERROR, "db_get_data", "\"%s\" is of type %s, not %s", pkey_name, rpc_tid_name(pkey_type), rpc_tid_name(type));
6702  return DB_TYPE_MISMATCH;
6703  }
6704 
6705  /* keys cannot contain data */
6706  if (pkey->type == TID_KEY) {
6708  cm_msg(MERROR, "db_get_data", "Key cannot contain data");
6709  return DB_TYPE_MISMATCH;
6710  }
6711 
6712  /* check if key has data */
6713  if (pkey->data == 0) {
6714  memset(data, 0, *buf_size);
6715  *buf_size = 0;
6717  return DB_SUCCESS;
6718  }
6719 
6720  /* check if buffer is too small */
6721  if (pkey->num_values * pkey->item_size > *buf_size) {
6722  int pkey_size = pkey->num_values * pkey->item_size;
6723  memcpy(data, (char *) pheader + pkey->data, *buf_size);
6725  char str[MAX_ODB_PATH];
6726  db_get_path(hDB, hKey, str, sizeof(str));
6727  cm_msg(MERROR, "db_get_data", "data for key \"%s\" truncated from %d to %d bytes", str, pkey_size, *buf_size);
6728  return DB_TRUNCATED;
6729  }
6730 
6731  /* copy key data */
6732  memcpy(data, (char *) pheader + pkey->data, pkey->num_values * pkey->item_size);
6733  *buf_size = pkey->num_values * pkey->item_size;
6734 
6736 
6737  }
6738 #endif /* LOCAL_ROUTINES */
6739 
6740  return DB_SUCCESS;
6741 }
#define RPC_DB_GET_LINK_DATA
Definition: mrpc.h:92
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_my_client_locked()

DATABASE_CLIENT* db_get_my_client_locked ( DATABASE pdb)

Definition at line 1368 of file odb.cxx.

1369 {
1370  assert(pdb);
1371  assert(pdb->database_header);
1372 
1373  DATABASE_HEADER *pheader = pdb->database_header;
1374 
1375  int idx = pdb->client_index;
1376 
1377  if (idx < 0 || idx >= pheader->max_client_index || idx >= MAX_CLIENTS) {
1378  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);
1379  abort();
1380  }
1381 
1382  DATABASE_CLIENT* pclient = &pheader->client[idx]; // safe to dereference on "idx"
1383 
1384  if (pclient->name[0] == 0) {
1385  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);
1386  abort();
1387  }
1388 
1389  int pid = getpid();
1390 
1391  if (pclient->pid != pid) {
1392  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);
1393  abort();
1394  }
1395 
1396  //printf("db_get_my_client_locked: idx %d, name [%s], pid %d\n", idx, pclient->name, pid);
1397 
1398  return pclient;
1399 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_next_link()

INT EXPRT db_get_next_link ( HNDLE  hDB,
HNDLE  hKey,
HNDLE subkey_handle 
)

Definition at line 5806 of file odb.cxx.

5828 {
5829  if (rpc_is_remote())
5830  return rpc_call(RPC_DB_GET_NEXT_LINK, hDB, hKey, subkey_handle);
5831 
5832 #ifdef LOCAL_ROUTINES
5833  {
5834  DATABASE_HEADER *pheader;
5835  KEYLIST *pkeylist;
5836  KEY *pkey;
5837  INT descent;
5838 
5839  if (hDB > _database_entries || hDB <= 0) {
5840  cm_msg(MERROR, "db_enum_link", "invalid database handle");
5841  return DB_INVALID_HANDLE;
5842  }
5843 
5844  if (!_database[hDB - 1].attached) {
5845  cm_msg(MERROR, "db_enum_link", "invalid database handle");
5846  return DB_INVALID_HANDLE;
5847  }
5848 
5849  *subkey_handle = 0;
5850 
5851  /* first lock database */
5853 
5854  pheader = _database[hDB - 1].database_header;
5855  if (!hKey)
5856  hKey = pheader->root_key;
5857 
5858  /* check if hKey argument is correct */
5859  if (!db_validate_hkey(pheader, hKey)) {
5861  return DB_INVALID_HANDLE;
5862  }
5863 
5864  pkey = (KEY *) ((char *) pheader + hKey);
5865 
5866  descent = TRUE;
5867  do {
5868  if (pkey->type != TID_KEY || !descent) {
5869  if (pkey->next_key) {
5870  /* key has next key, return it */
5871  // FIXME: validate pkey->next_key
5872  pkey = (KEY *) ((char *) pheader + pkey->next_key);
5873 
5874  if (pkey->type != TID_KEY) {
5875  *subkey_handle = (POINTER_T) pkey - (POINTER_T) pheader;
5877  return DB_SUCCESS;
5878  }
5879 
5880  /* key has subkeys, so descent on the next iteration */
5881  descent = TRUE;
5882  } else {
5883  if (pkey->parent_keylist == 0) {
5884  /* return if we are back to the root key */
5886  return DB_NO_MORE_SUBKEYS;
5887  }
5888 
5889  /* key is last in list, traverse up */
5890  pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
5891 
5892  // FIXME: validate pkeylist->parent
5893  pkey = (KEY *) ((char *) pheader + pkeylist->parent);
5894  descent = FALSE;
5895  }
5896  } else {
5897  if (descent) {
5898  /* find first subkey */
5899  pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
5900 
5901  if (pkeylist->num_keys == 0) {
5902  /* if key has no subkeys, look for next key on this level */
5903  descent = FALSE;
5904  } else {
5905  /* get first subkey */
5906  // FIXME: validate pkeylist->first_key
5907  pkey = (KEY *) ((char *) pheader + pkeylist->first_key);
5908 
5909  if (pkey->type != TID_KEY) {
5910  *subkey_handle = (POINTER_T) pkey - (POINTER_T) pheader;
5912  return DB_SUCCESS;
5913  }
5914  }
5915  }
5916  }
5917 
5918  } while (TRUE);
5919  }
5920 #endif /* LOCAL_ROUTINES */
5921 
5922  return DB_SUCCESS;
5923 }
#define RPC_DB_GET_NEXT_LINK
Definition: mrpc.h:90
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_open_records()

INT EXPRT db_get_open_records ( HNDLE  hDB,
HNDLE  hKey,
char *  str,
INT  buf_size,
BOOL  fix 
)

Definition at line 5178 of file odb.cxx.

5200 {
5201  str[0] = 0;
5202 
5203  if (rpc_is_remote())
5204  return rpc_call(RPC_DB_GET_OPEN_RECORDS, hDB, hKey, str, buf_size);
5205 
5206  std::string result;
5207 
5208 #ifdef LOCAL_ROUTINES
5209 
5210  if (fix)
5211  db_scan_tree(hDB, hKey, 0, db_fix_open_records, &result); // FIXME: should use db_scan_tree_wlocked()
5212  else
5213  db_scan_tree(hDB, hKey, 0, db_find_open_records, &result); // FIXME: should use db_scan_tree_locked()
5214 
5215 #endif
5216 
5217  strlcpy(str, result.c_str(), buf_size);
5218 
5219  return DB_SUCCESS;
5220 }
INT db_scan_tree(HNDLE hDB, HNDLE hKey, INT level, INT(*callback)(HNDLE, HNDLE, KEY *, INT, void *), void *info)
Definition: odb.cxx:4757
static int db_fix_open_records(HNDLE hDB, HNDLE hKey, KEY *key, INT level, void *xresult)
Definition: odb.cxx:5136
static int db_find_open_records(HNDLE hDB, HNDLE hKey, KEY *key, INT level, void *xresult)
Definition: odb.cxx:5094
#define RPC_DB_GET_OPEN_RECORDS
Definition: mrpc.h:83
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_parent() [1/2]

static const KEY* db_get_parent ( const DATABASE_HEADER pheader,
const KEY pkey,
int *  pstatus,
const char *  caller,
db_err_msg **  msg 
)
static

Definition at line 1033 of file odb.cxx.

1034 {
1035  if (pkey->parent_keylist == 0) {
1036  // they asked for the parent of "/", return "/"
1037  return db_get_pkey(pheader, pheader->root_key, pstatus, caller, msg);
1038  }
1039 
1040  if (!db_validate_data_offset(pheader, pkey->parent_keylist)) {
1041  db_msg(msg, MERROR, caller, "hkey %d path \"%s\" invalid pkey->parent %d", db_pkey_to_hkey(pheader, pkey), db_get_path_locked(pheader, pkey).c_str(), pkey->parent_keylist);
1042  if (pstatus)
1043  *pstatus = DB_CORRUPTED;
1044  return NULL;
1045  }
1046 
1047  const KEYLIST *pkeylist = (const KEYLIST *) ((char *) pheader + pkey->parent_keylist);
1048 
1049  if (pkeylist->first_key == 0 && pkeylist->num_keys != 0) {
1050  db_msg(msg, MERROR, caller, "hkey %d path \"%s\" invalid parent pkeylist->first_key %d should be non zero for num_keys %d", db_pkey_to_hkey(pheader, pkey), db_get_path_locked(pheader, pkey).c_str(), pkeylist->first_key, pkeylist->num_keys);
1051  if (pstatus)
1052  *pstatus = DB_CORRUPTED;
1053  return NULL;
1054  }
1055 
1056  return db_get_pkey(pheader, pkeylist->parent, pstatus, caller, msg);
1057 }
static bool db_validate_data_offset(const DATABASE_HEADER *pheader, int offset)
Definition: odb.cxx:908
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_parent() [2/2]

INT EXPRT db_get_parent ( HNDLE  hDB,
HNDLE  hKey,
HNDLE parenthKey 
)

Definition at line 4689 of file odb.cxx.

4707 {
4708  if (rpc_is_remote())
4709  return rpc_call(RPC_DB_GET_PARENT, hDB, hKey, parenthKey);
4710 
4711 #ifdef LOCAL_ROUTINES
4712  {
4713 
4714  DATABASE_HEADER *pheader;
4715  const KEY *pkey;
4716 
4717  if (hDB > _database_entries || hDB <= 0) {
4718  cm_msg(MERROR, "db_get_parent", "invalid database handle");
4719  return DB_INVALID_HANDLE;
4720  }
4721 
4722  if (!_database[hDB - 1].attached) {
4723  cm_msg(MERROR, "db_get_parent", "invalid database handle");
4724  return DB_INVALID_HANDLE;
4725  }
4726 
4727  if (hKey < (int) sizeof(DATABASE_HEADER)) {
4728  cm_msg(MERROR, "db_get_parent", "invalid key handle");
4729  return DB_INVALID_HANDLE;
4730  }
4731 
4733 
4734  pheader = _database[hDB - 1].database_header;
4735  pkey = (const KEY *) ((char *) pheader + hKey);
4736 
4737  /* find parent key */
4738  const KEYLIST *pkeylist = (const KEYLIST *) ((char *) pheader + pkey->parent_keylist);
4739 
4740  if (!db_validate_hkey(pheader, pkeylist->parent)) {
4742  return DB_INVALID_HANDLE;
4743  }
4744 
4745  pkey = (const KEY *) ((char *) pheader + pkeylist->parent);
4746 
4747  *parenthKey = (POINTER_T) pkey - (POINTER_T) pheader;
4748 
4750  }
4751 #endif
4752 
4753  return DB_SUCCESS;
4754 }
#define RPC_DB_GET_PARENT
Definition: mrpc.h:97
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_path() [1/2]

std::string EXPRT db_get_path ( HNDLE  hDB,
HNDLE  hKey 
)

Definition at line 5039 of file odb.cxx.

5053 {
5054  if (rpc_is_remote()) {
5055  char path[MAX_ODB_PATH];
5056  int status = rpc_call(RPC_DB_GET_PATH, hDB, hKey, path, sizeof(path));
5057  if (status != DB_SUCCESS) {
5058  sprintf(path, "(RPC_DB_GET_PATH status %d)", status);
5059  }
5060  return path;
5061  }
5062 
5063 #ifdef LOCAL_ROUTINES
5064  {
5065  DATABASE_HEADER *pheader;
5066 
5067  if (hDB > _database_entries || hDB <= 0) {
5068  cm_msg(MERROR, "db_get_path", "invalid database handle");
5069  return "(DB_INVALID_HANDLE)";
5070  }
5071 
5072  if (!_database[hDB - 1].attached) {
5073  cm_msg(MERROR, "db_get_path", "invalid database handle");
5074  return "(DB_INVALID_HANDLE)";
5075  }
5076 
5078 
5079  pheader = _database[hDB - 1].database_header;
5080 
5081  std::string xpath = db_get_path_locked(pheader, hKey);
5082 
5084 
5085  return xpath;
5086  }
5087 #endif /* LOCAL_ROUTINES */
5088 
5089  return "(no LOCAL_ROUTINES)";
5090 }
#define RPC_DB_GET_PATH
Definition: mrpc.h:61
Here is the call graph for this function:

◆ db_get_path() [2/2]

INT EXPRT db_get_path ( HNDLE  hDB,
HNDLE  hKey,
char *  path,
INT  buf_size 
)

Definition at line 4980 of file odb.cxx.

5003 {
5004  if (rpc_is_remote())
5005  return rpc_call(RPC_DB_GET_PATH, hDB, hKey, path, buf_size);
5006 
5007 #ifdef LOCAL_ROUTINES
5008  {
5009  DATABASE_HEADER *pheader;
5010 
5011  if (hDB > _database_entries || hDB <= 0) {
5012  cm_msg(MERROR, "db_get_path", "invalid database handle");
5013  return DB_INVALID_HANDLE;
5014  }
5015 
5016  if (!_database[hDB - 1].attached) {
5017  cm_msg(MERROR, "db_get_path", "invalid database handle");
5018  return DB_INVALID_HANDLE;
5019  }
5020 
5022 
5023  pheader = _database[hDB - 1].database_header;
5024 
5025  std::string xpath = db_get_path_locked(pheader, hKey);
5026 
5028 
5029  strlcpy(path, xpath.c_str(), buf_size);
5030 
5031  return DB_SUCCESS;
5032  }
5033 #endif /* LOCAL_ROUTINES */
5034 
5035  return DB_SUCCESS;
5036 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_path_locked() [1/2]

static std::string db_get_path_locked ( const DATABASE_HEADER pheader,
const KEY pkey 
)
static

Definition at line 4891 of file odb.cxx.

4892 {
4893  std::string path = "";
4894  while (1) {
4895  //printf("db_get_path_locked: hkey %d, pkey name \"%s\", type %d, parent %d, path \"%s\"\n", hKey, pkey->name, pkey->type, pkey->parent_keylist, path.c_str());
4896 
4897  /* check key type */
4898  if (pkey->type <= 0 || pkey->type >= TID_LAST) {
4899  char buf[256];
4900  sprintf(buf, "(INVALID_KEY_TYPE_%d)", pkey->type);
4901  std::string xpath;
4902  xpath += buf;
4903  if (path.length() > 0) {
4904  xpath += "/";
4905  xpath += path;
4906  }
4907  return xpath;
4908  }
4909 
4910  /* add key name in front of path */
4911  std::string str = path;
4912  path = "";
4913  if (pkey->name[0] == 0) {
4914  path += "(EMPTY_NAME)";
4915  } else {
4916  path += pkey->name;
4917  }
4918  if (str.length() > 0)
4919  path += "/";
4920  path += str;
4921 
4922  if (!pkey->parent_keylist) {
4923  return path;
4924  }
4925 
4926  if (!db_validate_data_offset(pheader, pkey->parent_keylist)) {
4927  return "(INVALID_PARENT_KEYLIST)/" + path;
4928  }
4929 
4930  /* find parent key */
4931  const KEYLIST* pkeylist = (const KEYLIST *) ((char *) pheader + pkey->parent_keylist);
4932 
4933  if (pkeylist->parent == pheader->root_key) {
4934  return "/" + path;
4935  }
4936 
4937  if (pkeylist->parent == 0) {
4938  return "(NULL_PARENT)/" + path;
4939  }
4940 
4941  if (!db_validate_key_offset(pheader, pkeylist->parent)) {
4942  return "(INVALID_PARENT)/" + path;
4943  }
4944 
4945  pkey = (const KEY *) ((char *) pheader + pkeylist->parent);
4946  };
4947 
4948  /* NOT REACHED */
4949 }
Here is the call graph for this function:

◆ db_get_path_locked() [2/2]

static std::string db_get_path_locked ( const DATABASE_HEADER pheader,
HNDLE  hKey 
)
static

Definition at line 4952 of file odb.cxx.

4953 {
4954  //printf("db_get_path_locked: hkey %d\n", hKey);
4955 
4956  if (!hKey)
4957  hKey = pheader->root_key;
4958 
4959  if (hKey == pheader->root_key) {
4960  return "/";
4961  }
4962 
4963  /* check if hKey argument is correct */
4964  if (hKey == 0) {
4965  return "(ZERO_HKEY)";
4966  }
4967 
4968  /* check if hKey argument is correct */
4969  if (!db_validate_key_offset(pheader, hKey)) {
4970  return "(INVALID_HKEY)";
4971  }
4972 
4973  const KEY* pkey = (const KEY *) ((char *) pheader + hKey);
4974 
4975  return db_get_path_locked(pheader, pkey);
4976 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_pkey()

static const KEY* db_get_pkey ( const DATABASE_HEADER pheader,
HNDLE  hKey,
int *  pstatus,
const char *  caller,
db_err_msg **  msg 
)
static

Definition at line 933 of file odb.cxx.

934 {
935  BOOL hKey_is_root_key = FALSE;
936 
937  if (!hKey) {
938  hKey_is_root_key = TRUE;
939  hKey = pheader->root_key;
940  }
941 
942  /* check if hKey argument is correct */
943  if (hKey == 0) {
944  if (pstatus)
945  *pstatus = DB_INVALID_HANDLE;
946  return NULL;
947  }
948 
949  /* check if hKey argument is correct */
950  if (!db_validate_key_offset(pheader, hKey)) {
951  if (pstatus)
952  *pstatus = DB_INVALID_HANDLE;
953  return NULL;
954  }
955 
956  const KEY* pkey = (const KEY *) ((char *) pheader + hKey);
957 
958  if (pkey->type < 1 || pkey->type >= TID_LAST) {
959  DWORD tid = pkey->type;
960  if (hKey_is_root_key) {
961  db_msg(msg, MERROR, caller, "db_get_pkey: root_key hkey %d invalid key type %d, database root directory is corrupted", hKey, tid);
962  if (pstatus)
963  *pstatus = DB_CORRUPTED;
964  return NULL;
965  } else {
966  std::string path = db_get_path_locked(pheader, hKey);
967  db_msg(msg, MERROR, caller, "db_get_pkey: hkey %d path \"%s\" invalid key type %d", hKey, path.c_str(), tid);
968  }
969  if (pstatus)
970  *pstatus = DB_NO_KEY;
971  return NULL;
972  }
973 
974  if (pkey->name[0] == 0) {
975  std::string path = db_get_path_locked(pheader, hKey);
976  db_msg(msg, MERROR, caller, "db_get_pkey: hkey %d path \"%s\" invalid name \"%s\" is empty", hKey, path.c_str(), pkey->name);
977  if (pstatus)
978  *pstatus = DB_NO_KEY;
979  return NULL;
980  }
981 
982  return pkey;
983 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_pkeylist()

static const KEYLIST* db_get_pkeylist ( const DATABASE_HEADER pheader,
HNDLE  hKey,
const KEY pkey,
const char *  caller,
db_err_msg **  msg,
bool  kludge_repair = false 
)
static

Definition at line 985 of file odb.cxx.

986 {
987  if (pkey->type != TID_KEY) {
988  std::string path = db_get_path_locked(pheader, hKey);
989  db_msg(msg, MERROR, caller, "db_get_pkeylist: hkey %d path \"%s\" unexpected call to db_get_pkeylist(), not a subdirectory, pkey->type %d", hKey, path.c_str(), pkey->type);
990  return NULL;
991  }
992 
993  if (!hKey) {
994  hKey = pheader->root_key;
995  }
996 
997  if (!db_validate_data_offset(pheader, pkey->data)) {
998  std::string path = db_get_path_locked(pheader, hKey);
999  db_msg(msg, MERROR, caller, "hkey %d path \"%s\" invalid pkey->data %d", hKey, path.c_str(), pkey->data);
1000  return NULL;
1001  }
1002 
1003  const KEYLIST *pkeylist = (const KEYLIST *) ((char *) pheader + pkey->data);
1004 
1005  if (pkeylist->parent != hKey) {
1006  std::string path = db_get_path_locked(pheader, hKey);
1007  db_msg(msg, MERROR, caller, "hkey %d path \"%s\" invalid pkeylist->parent %d should be hkey %d", hKey, path.c_str(), pkeylist->parent, hKey);
1008  return NULL;
1009  }
1010 
1011  if (pkeylist->first_key == 0 && pkeylist->num_keys != 0) {
1012  if (!kludge_repair) {
1013  std::string path = db_get_path_locked(pheader, hKey);
1014  db_msg(msg, MERROR, caller, "hkey %d path \"%s\" invalid pkeylist->first_key %d should be non zero for num_keys %d", hKey, path.c_str(), pkeylist->first_key, pkeylist->num_keys);
1015  return NULL;
1016  }
1017 
1018  // FIXME: this repair should be done in db_validate_and_repair_key()
1019 
1020  std::string path = db_get_path_locked(pheader, hKey);
1021  db_msg(msg, MERROR, caller, "hkey %d path \"%s\" repaired invalid num_keys %d when pkeylist->first_key is zero", hKey, path.c_str(), pkeylist->num_keys);
1022  ((KEYLIST*)pkeylist)->num_keys = 0;
1023  }
1024 
1025  return pkeylist;
1026 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_record()

INT EXPRT db_get_record ( HNDLE  hDB,
HNDLE  hKey,
void *  data,
INT buf_size,
INT  align 
)

Copy a set of keys to local memory.

An ODB sub-tree can be mapped to a C structure automatically via a hot-link using the function db_open_record() or manually with this function. Problems might occur if the ODB sub-tree contains values which don't match the C structure. Although the structure size is checked against the sub-tree size, no checking can be done if the type and order of the values in the structure are the same than those in the ODB sub-tree. Therefore it is recommended to use the function db_create_record() before db_get_record() is used which ensures that both are equivalent.

struct {
INT level1;
INT level2;
char *trigger_settings_str =
"[Settings]\n\
level1 = INT : 0\n\
level2 = INT : 0";
{
HNDLE hDB, hkey;
INT size;
...
db_create_record(hDB, 0, "/Equipment/Trigger", trigger_settings_str);
db_find_key(hDB, 0, "/Equipment/Trigger/Settings", &hkey);
size = sizeof(trigger_settings);
db_get_record(hDB, hkey, &trigger_settings, &size, 0);
...
}
INT db_get_record(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT align)
Definition: odb.cxx:11713
Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
dataPointer to the retrieved data.
buf_sizeSize of data structure, must be obtained via sizeof(RECORD-NAME).
alignByte alignment calculated by the stub and passed to the rpc side to align data according to local machine. Must be zero when called from user level.
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_STRUCT_SIZE_MISMATCH

Definition at line 11713 of file odb.cxx.

11714 {
11715  if (rpc_is_remote()) {
11716  align = ss_get_struct_align();
11717  return rpc_call(RPC_DB_GET_RECORD, hDB, hKey, data, buf_size, align);
11718  }
11719 #ifdef LOCAL_ROUTINES
11720  {
11721  KEY key;
11722  INT convert_flags, status;
11723  INT total_size;
11724  void *pdata;
11725 
11726  if (data && buf_size) {
11727  memset(data, 0x00, *buf_size);
11728  }
11729 
11730  convert_flags = 0;
11731 
11732  if (!align)
11733  align = ss_get_struct_align();
11734  else {
11735  /* only convert data if called remotely, as indicated by align != 0 */
11736  if (rpc_is_mserver()) {
11737  convert_flags = rpc_get_convert_flags();
11738  }
11739  }
11740 
11741  /* check if key has subkeys */
11742  status = db_get_key(hDB, hKey, &key);
11743  if (status != DB_SUCCESS)
11744  return status;
11745 
11746  if (key.type != TID_KEY) {
11747  /* copy single key */
11748  if (key.item_size * key.num_values != *buf_size) {
11749  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, key.item_size * key.num_values);
11750  return DB_STRUCT_SIZE_MISMATCH;
11751  }
11752 
11753  db_get_data(hDB, hKey, data, buf_size, key.type);
11754 
11755  if (convert_flags) {
11756  if (key.num_values > 1)
11758  else
11759  rpc_convert_single(data, key.type, RPC_OUTGOING, convert_flags);
11760  }
11761 
11762  return DB_SUCCESS;
11763  }
11764 
11765  /* check record size */
11766  db_get_record_size(hDB, hKey, align, &total_size);
11767  if (total_size != *buf_size) {
11768  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);
11769  return DB_STRUCT_SIZE_MISMATCH;
11770  }
11771 
11772  /* get subkey data */
11773  pdata = data;
11774  total_size = 0;
11775 
11776  db_err_msg* msg = NULL;
11778  db_recurse_record_tree_locked(hDB, hKey, &pdata, &total_size, align, NULL, FALSE, convert_flags, &msg);
11780  if (msg)
11781  db_flush_msg(&msg);
11782 
11783  //if (total_size != *buf_size) {
11784  // cm_msg(MERROR, "db_get_record", "struct size mismatch for \"%s\", expected size: %d, read from ODB: %d bytes", db_get_path(hDB, hKey).c_str(), *buf_size, total_size);
11785  // //return DB_STRUCT_SIZE_MISMATCH;
11786  //}
11787  }
11788 #endif /* LOCAL_ROUTINES */
11789 
11790  return DB_SUCCESS;
11791 }
#define DB_STRUCT_SIZE_MISMATCH
Definition: midas.h:655
INT ss_get_struct_align()
Definition: system.cxx:1325
INT db_get_record_size(HNDLE hDB, HNDLE hKey, INT align, INT *buf_size)
Definition: odb.cxx:11619
static void db_recurse_record_tree_locked(HNDLE hDB, const DATABASE_HEADER *pheader, const KEY *pkey, void **data, INT *total_size, INT base_align, INT *max_align, BOOL bSet, INT convert_flags, db_err_msg **msg)
Definition: odb.cxx:11443
void rpc_convert_data(void *data, INT tid, INT flags, INT total_size, INT convert_flags)
Definition: midas.cxx:11673
void rpc_get_convert_flags(INT *convert_flags)
Definition: midas.cxx:11573
bool rpc_is_mserver(void)
Definition: midas.cxx:12785
void rpc_convert_single(void *data, INT tid, INT flags, INT convert_flags)
Definition: midas.cxx:11648
#define RPC_DB_GET_RECORD
Definition: mrpc.h:70
#define RPC_OUTGOING
Definition: midas.h:1583
#define RPC_FIXARRAY
Definition: midas.h:1581
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_record1()

INT EXPRT db_get_record1 ( HNDLE  hDB,
HNDLE  hKey,
void *  data,
INT buf_size,
INT  align,
const char *  rec_str 
)

Same as db_get_record() but if there is a record mismatch between ODB structure and C record, it is automatically corrected by calling db_check_record()

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
dataPointer to the retrieved data.
buf_sizeSize of data structure, must be obtained via sizeof(RECORD-NAME).
alignByte alignment calculated by the stub and passed to the rpc side to align data according to local machine. Must be zero when called from user level.
rec_strASCII representation of ODB record in the format
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_STRUCT_SIZE_MISMATCH

Definition at line 11809 of file odb.cxx.

11810 {
11811  int size = *buf_size;
11812  int odb_size = 0;
11813  int status;
11814  char path[MAX_ODB_PATH];
11815 
11816  /* check record size first */
11817 
11818  status = db_get_record_size(hDB, hKey, align, &odb_size);
11819  if (status != DB_SUCCESS)
11820  return status;
11821 
11822  /* if size mismatch, call repair function */
11823 
11824  if (odb_size != size) {
11825  db_get_path(hDB, hKey, path, sizeof(path));
11826  cm_msg(MINFO, "db_get_record1", "Fixing ODB \"%s\" struct size mismatch (expected %d, odb size %d)", path, size, odb_size);
11827  status = db_create_record(hDB, hKey, "", rec_str);
11828  if (status != DB_SUCCESS)
11829  return status;
11830  }
11831 
11832  /* run db_get_record(), if success, we are done */
11833 
11834  status = db_get_record(hDB, hKey, data, buf_size, align);
11835  if (status == DB_SUCCESS)
11836  return status;
11837 
11838  /* try repair with db_check_record() */
11839 
11840  status = db_check_record(hDB, hKey, "", rec_str, TRUE);
11841  if (status != DB_SUCCESS)
11842  return status;
11843 
11844  /* verify struct size again, because there can still be a mismatch if there
11845  * are extra odb entries at the end of the record as db_check_record()
11846  * seems to ignore all odb entries past the end of "rec_str". K.O.
11847  */
11848 
11849  status = db_get_record_size(hDB, hKey, align, &odb_size);
11850  if (status != DB_SUCCESS)
11851  return status;
11852 
11853  db_get_path(hDB, hKey, path, sizeof(path));
11854 
11855  if (odb_size != size) {
11856  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);
11857  status = db_create_record(hDB, hKey, "", rec_str);
11858  if (status != DB_SUCCESS)
11859  return status;
11860  }
11861 
11862  cm_msg(MERROR, "db_get_record1", "repaired struct size mismatch of \"%s\"", path);
11863 
11864  *buf_size = size;
11865  status = db_get_record(hDB, hKey, data, buf_size, align);
11866 
11867  return status;
11868 }
INT db_check_record(HNDLE hDB, HNDLE hKey, const char *keyname, const char *rec_str, BOOL correct)
Definition: odb.cxx:12975
INT odb_size
Definition: analyzer.cxx:46
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_record2()

INT EXPRT db_get_record2 ( HNDLE  hDB,
HNDLE  hKey,
void *  data,
INT xbuf_size,
INT  align,
const char *  rec_str,
BOOL  correct 
)

Copy a set of keys to local memory.

An ODB sub-tree can be mapped to a C structure automatically via a hot-link using the function db_open_record1() or manually with this function. For correct operation, the description string must match the C data structure. If the contents of ODB sub-tree does not exactly match the description string, db_get_record2() will try to read as much as it can and return DB_TRUNCATED to inform the user that there was a mismatch somewhere. To ensure that the ODB sub-tree matches the desciption string, call db_create_record() or db_check_record() before calling db_get_record2(). Unlike db_get_record() and db_get_record1(), this function will not complain about data strucure mismatches. It will ignore all extra entries in the ODB sub-tree and it will set to zero the C-structure data fields that do not have corresponding ODB entries.

struct {
INT level1;
INT level2;
const char *trigger_settings_str =
"[Settings]\n\
level1 = INT : 0\n\
level2 = INT : 0";
{
HNDLE hDB, hkey;
INT size;
...
db_create_record(hDB, 0, "/Equipment/Trigger", trigger_settings_str);
db_find_key(hDB, 0, "/Equipment/Trigger/Settings", &hkey);
size = sizeof(trigger_settings);
db_get_record2(hDB, hkey, &trigger_settings, &size, 0, trigger_settings_str);
...
}
INT db_get_record2(HNDLE hDB, HNDLE hKey, void *data, INT *xbuf_size, INT align, const char *rec_str, BOOL correct)
Definition: odb.cxx:12173
Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
dataPointer to the retrieved data.
buf_sizeSize of data structure, must be obtained via sizeof(data).
alignByte alignment calculated by the stub and passed to the rpc side to align data according to local machine. Must be zero when called from user level.
rec_strDescription of the data structure, see db_create_record()
correctMust be set to zero
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_STRUCT_SIZE_MISMATCH

Definition at line 12173 of file odb.cxx.

12174 {
12175  int status = DB_SUCCESS;
12176 
12177  printf("db_get_record2!\n");
12178 
12179  assert(data != NULL);
12180  assert(xbuf_size != NULL);
12181  assert(*xbuf_size > 0);
12182  assert(correct == 0);
12183 
12184  int truncated = 0;
12185 #if 1
12186  char* r1 = NULL;
12187  int rs = *xbuf_size;
12188  if (1) {
12189  r1 = (char*)malloc(rs);
12190  memset(data, 0xFF, *xbuf_size);
12191  memset(r1, 0xFF, rs);
12192  //status = db_get_record1(hDB, hKey, r1, &rs, 0, rec_str);
12193  status = db_get_record(hDB, hKey, r1, &rs, 0);
12194  printf("db_get_record status %d\n", status);
12195  }
12196 #endif
12197 
12198  char* buf_start = (char*)data;
12199  int buf_size = *xbuf_size;
12200 
12201  char* buf_ptr = buf_start;
12202  int buf_remain = buf_size;
12203 
12204  while (rec_str && *rec_str != 0) {
12205  char title[256];
12206  char key_name[MAX_ODB_PATH];
12207  int tid = 0;
12208  int n_data = 0;
12209  int string_length = 0;
12210  const char* rec_str_next = NULL;
12211 
12212  status = db_parse_record(rec_str, &rec_str_next, title, sizeof(title), key_name, sizeof(key_name), &tid, &n_data, &string_length);
12213 
12214  //printf("parse [%s], status %d, title [%s], key_name [%s], tid %d, n_data %d, string_length %d, next [%s]\n", rec_str, status, title, key_name, tid, n_data, string_length, rec_str_next);
12215 
12216  rec_str = rec_str_next;
12217 
12218  if (status != DB_SUCCESS) {
12219  return status;
12220  }
12221 
12222  if (key_name[0] == 0) {
12223  // skip title strings, comments, etc
12224  continue;
12225  }
12226 
12227  status = db_get_record2_read_element(hDB, hKey, key_name, tid, n_data, string_length, buf_start, &buf_ptr, &buf_remain, correct);
12228  if (status == DB_INVALID_PARAM) {
12229  cm_msg(MERROR, "db_get_record2", "error: cannot continue reading odb record because of previous fatal error, status %d", status);
12230  return DB_INVALID_PARAM;
12231  } if (status != DB_SUCCESS) {
12232  truncated = 1;
12233  }
12234 
12235  rec_str = rec_str_next;
12236  }
12237 
12238  if (r1) {
12239  int ok = -1;
12240  int i;
12241  for (i=0; i<rs; i++) {
12242  if (r1[i] != buf_start[i]) {
12243  ok = i;
12244  break;
12245  }
12246  }
12247  if (ok>=0 || buf_remain>0) {
12248  printf("db_get_record2: miscompare at %d out of %d, buf_remain %d\n", ok, rs, buf_remain);
12249  } else {
12250  printf("db_get_record2: check ok\n");
12251  }
12252  }
12253 
12254  if (buf_remain > 0) {
12255  // FIXME: we finished processing the data definition string, but unused space remains in the buffer
12256  return DB_TRUNCATED;
12257  }
12258 
12259  if (truncated)
12260  return DB_TRUNCATED;
12261  else
12262  return DB_SUCCESS;
12263 }
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)
Definition: odb.cxx:12053
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)
Definition: odb.cxx:11870
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_record2_read_element()

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 
)
static

Definition at line 12053 of file odb.cxx.

12054 {
12055  assert(tid > 0);
12056  assert(n_data > 0);
12057  int tsize = rpc_tid_size(tid);
12058  int offset = *buf_ptr - buf_start;
12059  int align = 0;
12060  if (tsize && (offset%tsize != 0)) {
12061  while (offset%tsize != 0) {
12062  align++;
12063  *(*buf_ptr) = 0xFF; // pad bytes for correct data alignement
12064  (*buf_ptr)++;
12065  (*buf_remain)--;
12066  offset++;
12067  }
12068  }
12069  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);
12070  if (tsize > 0) {
12071  int xsize = tsize*n_data;
12072  if (xsize > *buf_remain) {
12073  cm_msg(MERROR, "db_get_record2", "buffer overrun at key \"%s\", size %d, buffer remaining %d", key_name, xsize, *buf_remain);
12074  return DB_INVALID_PARAM;
12075  }
12076  int ysize = xsize;
12077  int status = db_get_value(hDB, hKey, key_name, *buf_ptr, &ysize, tid, FALSE);
12078  //printf("status %d, xsize %d\n", status, xsize);
12079  if (status != DB_SUCCESS) {
12080  cm_msg(MERROR, "db_get_record2", "cannot read \"%s\", db_get_value() status %d", key_name, status);
12081  memset(*buf_ptr, 0, xsize);
12082  *buf_ptr += xsize;
12083  *buf_remain -= xsize;
12084  return status;
12085  }
12086  *buf_ptr += xsize;
12087  *buf_remain -= xsize;
12088  } else if (tid == TID_STRING) {
12089  int xstatus = 0;
12090  int i;
12091  for (i=0; i<n_data; i++) {
12092  int xsize = string_length;
12093  if (xsize > *buf_remain) {
12094  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);
12095  return DB_INVALID_PARAM;
12096  }
12097  char xkey_name[MAX_ODB_PATH+100];
12098  sprintf(xkey_name, "%s[%d]", key_name, i);
12099  int status = db_get_value(hDB, hKey, xkey_name, *buf_ptr, &xsize, tid, FALSE);
12100  //printf("status %d, string length %d, xsize %d, actual len %d\n", status, string_length, xsize, (int)strlen(*buf_ptr));
12101  if (status == DB_TRUNCATED) {
12102  // make sure string is NUL terminated
12103  (*buf_ptr)[string_length-1] = 0;
12104  cm_msg(MERROR, "db_get_record2", "string key \"%s\" index %d, string value was truncated", key_name, i);
12105  } else if (status != DB_SUCCESS) {
12106  cm_msg(MERROR, "db_get_record2", "cannot read string \"%s\"[%d], db_get_value() status %d", key_name, i, status);
12107  memset(*buf_ptr, 0, string_length);
12108  xstatus = status;
12109  }
12110  *buf_ptr += string_length;
12111  *buf_remain -= string_length;
12112  }
12113  if (xstatus != 0) {
12114  return xstatus;
12115  }
12116  } else {
12117  cm_msg(MERROR, "db_get_record2", "cannot read key \"%s\" of unsupported type %d", key_name, tid);
12118  return DB_INVALID_PARAM;
12119  }
12120  return DB_SUCCESS;
12121 }
static int offset
Definition: mgd.cxx:1500
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_record_size()

INT EXPRT db_get_record_size ( HNDLE  hDB,
HNDLE  hKey,
INT  align,
INT buf_size 
)

dox Calculates the size of a record.

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
alignByte alignment calculated by the stub and passed to the rpc side to align data according to local machine. Must be zero when called from user level
buf_sizeSize of record structure
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_TYPE_MISMATCH, DB_STRUCT_SIZE_MISMATCH, DB_NO_KEY

Definition at line 11619 of file odb.cxx.

11620 {
11621  if (rpc_is_remote()) {
11622  align = ss_get_struct_align();
11623  return rpc_call(RPC_DB_GET_RECORD_SIZE, hDB, hKey, align, buf_size);
11624  }
11625 #ifdef LOCAL_ROUTINES
11626  {
11627  KEY key;
11628  INT status, max_align;
11629 
11630  if (!align)
11631  align = ss_get_struct_align();
11632 
11633  /* check if key has subkeys */
11634  status = db_get_key(hDB, hKey, &key);
11635  if (status != DB_SUCCESS)
11636  return status;
11637 
11638  if (key.type != TID_KEY) {
11639  /* just a single key */
11640  *buf_size = key.item_size * key.num_values;
11641  return DB_SUCCESS;
11642  }
11643 
11644  db_err_msg* msg = NULL;
11646 
11647  /* determine record size */
11648  *buf_size = max_align = 0;
11649  db_recurse_record_tree_locked(hDB, hKey, NULL, buf_size, align, &max_align, 0, 0, &msg);
11650 
11651  //int tmp = *buf_size;
11652  /* correct for byte padding */
11653  *buf_size = VALIGN(*buf_size, max_align);
11654 
11655  //if (tmp != *buf_size) {
11656  // cm_msg(MERROR, "db_get_record_size", "ODB record \"%s\" has unexpected padding from %d to %d bytes", db_get_path(hDB, hKey).c_str(), tmp, *buf_size);
11657  //}
11658 
11660  if (msg)
11661  db_flush_msg(&msg);
11662  }
11663 #endif /* LOCAL_ROUTINES */
11664 
11665  return DB_SUCCESS;
11666 }
#define VALIGN(adr, align)
Definition: midas.h:532
#define RPC_DB_GET_RECORD_SIZE
Definition: mrpc.h:69
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_value()

INT EXPRT db_get_value ( HNDLE  hDB,
HNDLE  hKeyRoot,
const char *  key_name,
void *  data,
INT buf_size,
DWORD  type,
BOOL  create 
)

Get value of a single key.

The function returns single values or whole arrays which are contained in an ODB key. Since the data buffer is of type void, no type checking can be performed by the compiler. Therefore the type has to be explicitly supplied, which is checked against the type stored in the ODB. key_name can contain the full path of a key (like: "/Equipment/Trigger/Settings/Level1") while hkey is zero which refers to the root, or hkey can refer to a sub-directory (like: /Equipment/Trigger) and key_name is interpreted relative to that directory like "Settings/Level1".

INT level1, size;
size = sizeof(level1);
db_get_value(hDB, 0, "/Equipment/Trigger/Settings/Level1",
&level1, &size, TID_INT32, 0);
Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyRootHandle for key where search starts, zero for root.
key_nameName of key to search, can contain directories.
dataAddress of data.
buf_sizeMaximum buffer size on input, number of written bytes on return.
typeType of key, one of TID_xxx (see Midas_Data_Types)
createIf TRUE, create key if not existing
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_NO_ACCESS, DB_TYPE_MISMATCH, DB_TRUNCATED, DB_NO_KEY

Definition at line 5405 of file odb.cxx.

5406 {
5407  if (rpc_is_remote())
5408  return rpc_call(RPC_DB_GET_VALUE, hDB, hKeyRoot, key_name, data, buf_size, type, create);
5409 
5410 #ifdef LOCAL_ROUTINES
5411  {
5412  INT status;
5413 
5414  if (hDB > _database_entries || hDB <= 0) {
5415  cm_msg(MERROR, "db_get_value", "invalid database handle %d", hDB);
5416  return DB_INVALID_HANDLE;
5417  }
5418 
5419  if (!_database[hDB - 1].attached) {
5420  cm_msg(MERROR, "db_get_value", "invalid database handle %d", hDB);
5421  return DB_INVALID_HANDLE;
5422  }
5423 
5424  /* check if key name contains index */
5425  char keyname[MAX_ODB_PATH];
5426  strlcpy(keyname, key_name, sizeof(keyname));
5427  int idx = -1;
5428  if (strchr(keyname, '[') && strchr(keyname, ']')) {
5429  char* p;
5430  for (p = strchr(keyname, '[') + 1; *p && *p != ']'; p++)
5431  if (!isdigit(*p))
5432  break;
5433 
5434  if (*p && *p == ']') {
5435  idx = atoi(strchr(keyname, '[') + 1);
5436  *strchr(keyname, '[') = 0;
5437  }
5438  }
5439 
5440  /* now lock database */
5442 
5443  DATABASE_HEADER* pheader = _database[hDB - 1].database_header;
5444  db_err_msg* msg = NULL;
5445 
5446  const KEY* pkey_root = db_get_pkey(pheader, hKeyRoot, &status, "db_get_value", &msg);
5447 
5448  if (!pkey_root) {
5450  if (msg)
5451  db_flush_msg(&msg);
5452  return status;
5453  }
5454 
5455  const KEY* pkey = db_find_pkey_locked(pheader, pkey_root, keyname, &status, &msg);
5456 
5457  if (!pkey) {
5458  if (create) {
5459  db_allow_write_locked(&_database[hDB-1], "db_get_value");
5460  /* set default value if key was created */
5461 
5462  /* get string size from data size */
5463  int size;
5464  if (type == TID_STRING || type == TID_LINK)
5465  size = *buf_size;
5466  else
5467  size = rpc_tid_size(type);
5468 
5469  status = db_set_value_wlocked(pheader, hDB, (KEY*)pkey_root, keyname, data, *buf_size, *buf_size / size, type, &msg);
5471  if (msg)
5472  db_flush_msg(&msg);
5473  return status;
5474  } else {
5476  if (msg)
5477  db_flush_msg(&msg);
5478  return DB_NO_KEY;
5479  }
5480  }
5481 
5482  status = db_get_data_locked(pheader, pkey, idx, data, buf_size, type, &msg);
5483 
5485  if (msg)
5486  db_flush_msg(&msg);
5487 
5488  return status;
5489  }
5490 #endif /* LOCAL_ROUTINES */
5491 
5492  return DB_SUCCESS;
5493 }
#define RPC_DB_GET_VALUE
Definition: mrpc.h:58
BOOL create
Definition: mchart.cxx:39
Here is the call graph for this function:

◆ db_get_value_string()

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 
)

Definition at line 13937 of file odb.cxx.

13938 {
13939  int status;
13940  int hkey;
13941 
13942  //printf("db_get_value_string: key_name [%s], index %d, string [%s], create %d, create_string_length %d\n", key_name, index, s->c_str(), create, create_string_length);
13943 
13944  if (index > 0 && create) {
13945  cm_msg(MERROR, "db_get_value_string", "cannot resize odb string arrays, please use db_resize_string() instead");
13946  return DB_OUT_OF_RANGE;
13947  }
13948 
13949  status = db_find_key(hdb, hKeyRoot, key_name, &hkey);
13950  if (status == DB_SUCCESS) {
13951  KEY key;
13952  status = db_get_key(hdb, hkey, &key);
13953  if (status != DB_SUCCESS)
13954  return status;
13955  if (index < 0 || index >= key.num_values)
13956  return DB_OUT_OF_RANGE;
13957  int size = key.item_size;
13958  if (size == 0) {
13959  if (s)
13960  *s = "";
13961  //printf("db_get_value_string: return empty string, item_size %d\n", key.item_size);
13962  return DB_SUCCESS;
13963  }
13964  char* buf = (char*)malloc(size);
13965  assert(buf != NULL);
13966  status = db_get_data_index(hdb, hkey, buf, &size, index, TID_STRING);
13967  if (status != DB_SUCCESS) {
13968  free(buf);
13969  return status;
13970  }
13971  if (s)
13972  *s = buf;
13973  free(buf);
13974  //printf("db_get_value_string: return [%s], len %d, item_size %d, size %d\n", s->c_str(), s->length(), key.item_size, size);
13975  return DB_SUCCESS;
13976  } else if (!create) {
13977  // does not exist and not asked to create it
13978  return status;
13979  } else {
13980  //printf("db_get_value_string: creating [%s]\n", key_name);
13981  status = db_create_key(hdb, hKeyRoot, key_name, TID_STRING);
13982  if (status != DB_SUCCESS)
13983  return status;
13984  status = db_find_key(hdb, hKeyRoot, key_name, &hkey);
13985  if (status != DB_SUCCESS)
13986  return status;
13987  assert(s != NULL);
13988  if (create_string_length == 0) {
13989  int size = s->length() + 1; // 1 byte for final \0
13990  status = db_set_data_index(hdb, hkey, s->c_str(), size, index, TID_STRING);
13991  } else {
13992  char* buf = (char*)malloc(create_string_length);
13993  assert(buf);
13994  strlcpy(buf, s->c_str(), create_string_length);
13995  status = db_set_data_index(hdb, hkey, buf, create_string_length, index, TID_STRING);
13996  free(buf);
13997  }
13998  if (status != DB_SUCCESS)
13999  return status;
14000  //printf("db_get_value_string: created with value [%s]\n", s->c_str());
14001  return DB_SUCCESS;
14002  }
14003  // NOT REACHED
14004 }
INT db_set_data_index(HNDLE hDB, HNDLE hKey, const void *data, INT data_size, INT idx, DWORD type)
Definition: odb.cxx:7642
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_watchdog_info()

INT db_get_watchdog_info ( HNDLE  hDB,
const char *  client_name,
DWORD timeout,
DWORD last 
)

Return watchdog information about specific client

Parameters
hDBODB handle
client_nameODB client name
timeoutTimeout for this application in seconds
lastLast time watchdog was called in msec
Returns
CM_SUCCESS, CM_NO_CLIENT, DB_INVALID_HANDLE

Definition at line 3004 of file odb.cxx.

3005 {
3006  if (hDB > _database_entries || hDB <= 0) {
3007  cm_msg(MERROR, "db_get_watchdog_info", "invalid database handle");
3008  return DB_INVALID_HANDLE;
3009  }
3010 
3011  if (!_database[hDB - 1].attached) {
3012  cm_msg(MERROR, "db_get_watchdog_info", "invalid database handle");
3013  return DB_INVALID_HANDLE;
3014  }
3015 
3016  /* lock database */
3018 
3019  DATABASE *pdb = &_database[hDB - 1];
3020  DATABASE_HEADER *pheader = pdb->database_header;
3021 
3022  /* find client */
3023  for (int i = 0; i < pheader->max_client_index; i++) {
3024  DATABASE_CLIENT *pclient = &pheader->client[i];
3025  if (pclient->pid && equal_ustring(pclient->name, client_name)) {
3026  *timeout = pclient->watchdog_timeout;
3027  *last = ss_millitime() - pclient->last_activity;
3029  return DB_SUCCESS;
3030  }
3031  }
3032 
3033  *timeout = *last = 0;
3034 
3036 
3037  return CM_NO_CLIENT;
3038 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_load()

INT EXPRT db_load ( HNDLE  hDB,
HNDLE  hKeyRoot,
const char *  filename,
BOOL  bRemote 
)

dox Load a branch of a database from an .ODB file.

This function is used by the ODBEdit command load. For a description of the ASCII format, see db_copy(). Data can be loaded relative to the root of the ODB (hkey equal zero) or relative to a certain key.

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyRootHandle for key where search starts, zero for root.
filenameFilename of .ODB file.
bRemoteIf TRUE, the file is loaded by the server process on the back-end, if FALSE, it is loaded from the current process
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_FILE_ERROR

Definition at line 8120 of file odb.cxx.

8121 {
8122  struct stat stat_buf;
8123  INT hfile, size, n, i, status;
8124  char *buffer;
8125 
8126  if (rpc_is_remote() && bRemote)
8127  return rpc_call(RPC_DB_LOAD, hDB, hKeyRoot, filename);
8128 
8129  /* open file */
8130  hfile = open(filename, O_RDONLY | O_TEXT, 0644);
8131  if (hfile == -1) {
8132  cm_msg(MERROR, "db_load", "file \"%s\" not found", filename);
8133  return DB_FILE_ERROR;
8134  }
8135 
8136  /* allocate buffer with file size */
8137  fstat(hfile, &stat_buf);
8138  size = stat_buf.st_size;
8139  buffer = (char *) malloc(size + 1);
8140 
8141  if (buffer == NULL) {
8142  cm_msg(MERROR, "db_load", "cannot allocate ODB load buffer");
8143  close(hfile);
8144  return DB_NO_MEMORY;
8145  }
8146 
8147  n = 0;
8148 
8149  do {
8150  i = read(hfile, buffer + n, size - n);
8151  if (i <= 0)
8152  break;
8153  n += i;
8154  } while (TRUE);
8155 
8156  buffer[n] = 0;
8157 
8158  if (strncmp(buffer, "<?xml version=\"1.0\"", 19) == 0) {
8159  status = db_paste_xml(hDB, hKeyRoot, buffer);
8160  if (status != DB_SUCCESS)
8161  printf("Error in file \"%s\"\n", filename);
8162  } else if( buffer[0] == '{'){
8163  if(strrchr(buffer, '}')){
8164  status = db_paste_json(hDB, hKeyRoot, buffer);
8165  } else {
8167  }
8168  } else
8169  status = db_paste(hDB, hKeyRoot, buffer);
8170 
8171  close(hfile);
8172  free(buffer);
8173 
8174  return status;
8175 }
#define DB_FILE_ERROR
Definition: midas.h:653
#define O_TEXT
Definition: msystem.h:220
INT db_paste_xml(HNDLE hDB, HNDLE hKeyRoot, const char *buffer)
Definition: odb.cxx:8998
INT EXPRT db_paste_json(HNDLE hDB, HNDLE hKeyRoot, const char *buffer)
Definition: json_paste.cxx:691
#define RPC_DB_LOAD
Definition: mrpc.h:75
DWORD n[4]
Definition: mana.cxx:247
#define read(n, a, f)
Definition: midas_macro.h:242
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_load_json()

INT EXPRT db_load_json ( HNDLE  hdb,
HNDLE  key_handle,
const char *  filename 
)

Definition at line 18 of file json_paste.cxx.

19 {
20  int status;
21  //printf("db_load_json: filename [%s], handle %d\n", filename, hKey);
22 
23  FILE* fp = fopen(filename, "r");
24  if (!fp) {
25  cm_msg(MERROR, "db_load_json", "file \"%s\" not found", filename);
26  return DB_FILE_ERROR;
27  }
28 
29  std::string data;
30 
31  while (1) {
32  char buf[102400];
33  int rd = read(fileno(fp), buf, sizeof(buf)-1);
34  if (rd == 0)
35  break; // end of file
36  if (rd < 0) {
37  // error
38  cm_msg(MERROR, "db_load_json", "file \"%s\" read error %d (%s)", filename, errno, strerror(errno));
39  fclose(fp);
40  return DB_FILE_ERROR;
41  }
42  // make sure string is nul terminated
43  buf[sizeof(buf)-1] = 0;
44  data += buf;
45  }
46 
47  fclose(fp);
48  fp = NULL;
49 
50  //printf("file contents: [%s]\n", data.c_str());
51 
52  const char* jptr = strchr(data.c_str(), '{');
53 
54  if (!jptr) {
55  cm_msg(MERROR, "db_load_json", "file \"%s\" does not look like JSON data", filename);
56  fclose(fp);
57  return DB_FILE_ERROR;
58  }
59 
60  status = db_paste_json(hDB, hKey, jptr);
61 
62  if (status != DB_SUCCESS) {
63  cm_msg(MERROR, "db_load_json", "error loading JSON data from file \"%s\"", filename);
64  return status;
65  }
66 
67  return status;
68 }
static FILE * fp
Definition: mlxspeaker.cxx:24
Here is the call graph for this function:

◆ db_lock_database()

INT db_lock_database ( HNDLE  hDB)

dox Lock a database for exclusive access via system semaphore calls.

Parameters
hDBHandle to the database to lock
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_TIMEOUT

Definition at line 2446 of file odb.cxx.

2447 {
2448 #ifdef LOCAL_ROUTINES
2449  int status;
2450 
2451  if (hDB > _database_entries || hDB <= 0) {
2452  cm_msg(MERROR, "db_lock_database", "invalid database handle %d, aborting...", hDB);
2453  abort();
2454  return DB_INVALID_HANDLE;
2455  }
2456 
2457  /* obtain access mutex in multi-thread applications */
2458  status = ss_mutex_wait_for(_database[hDB - 1].mutex, _database[hDB - 1].timeout);
2459  if (status != SS_SUCCESS) {
2460  cm_msg(MERROR, "db_lock_database", "cannot lock ODB mutex, timeout %d ms, status %d, aborting...", _database[hDB - 1].timeout, status);
2461  abort();
2462  }
2463 
2464  /* protect this function against recursive call from signal handlers */
2465  if (_database[hDB - 1].inside_lock_unlock) {
2466  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");
2467  abort();
2468  }
2469 
2470  _database[hDB - 1].inside_lock_unlock = 1;
2471 
2472  //static int x = 0;
2473  //x++;
2474  //if (x > 5000) {
2475  // printf("inside db_lock_database(), press Ctrl-C now!\n");
2476  // sleep(5);
2477  //}
2478 
2479  // test recursive locking
2480  // static int out=0;
2481  // out++;
2482  // printf("HERE %d!\n", out);
2483  // if (out>10) abort();
2484  // db_lock_database(hDB);
2485  // printf("OUT %d!\n", out);
2486 
2487  if (_database[hDB - 1].lock_cnt == 0) {
2488  _database[hDB - 1].lock_cnt = 1;
2489  /* wait max. 5 minutes for semaphore (required if locking process is being debugged) */
2490  status = ss_semaphore_wait_for(_database[hDB - 1].semaphore, _database[hDB - 1].timeout);
2491  if (status == SS_TIMEOUT) {
2492  cm_msg(MERROR, "db_lock_database", "cannot lock ODB semaphore, timeout %d ms, exiting...", _database[hDB - 1].timeout);
2493  exit(1);
2494  }
2495  if (status != SS_SUCCESS) {
2496  cm_msg(MERROR, "db_lock_database", "cannot lock ODB semaphore, timeout %d ms, ss_semaphore_wait_for() status %d, aborting...", _database[hDB - 1].timeout, status);
2497  abort();
2498  }
2499  } else {
2500  _database[hDB - 1].lock_cnt++; // we have already the lock (recursive call), so just increase counter
2501  }
2502 
2503 #ifdef CHECK_LOCK_COUNT
2504  {
2505  char str[256];
2506 
2507  sprintf(str, "db_lock_database, lock_cnt=%d", _database[hDB - 1].lock_cnt);
2509  }
2510 #endif
2511 
2512  if (_database[hDB - 1].protect) {
2513  if (_database[hDB - 1].database_header == NULL) {
2514  int status;
2515  assert(!_database[hDB - 1].protect_read);
2516  assert(!_database[hDB - 1].protect_write);
2517  status = ss_shm_unprotect(_database[hDB - 1].shm_handle, &_database[hDB - 1].shm_adr, _database[hDB - 1].shm_size, TRUE, FALSE, "db_lock_database");
2518  if (status != SS_SUCCESS) {
2519  cm_msg(MERROR, "db_lock_database", "cannot lock ODB, ss_shm_unprotect(TRUE,FALSE) failed with status %d, aborting...", status);
2521  abort();
2522  }
2523  _database[hDB - 1].database_header = (DATABASE_HEADER *) _database[hDB - 1].shm_adr;
2524  _database[hDB - 1].protect_read = TRUE;
2526  }
2527  }
2528 
2529  _database[hDB - 1].inside_lock_unlock = 0;
2530 
2531 #endif /* LOCAL_ROUTINES */
2532 
2533  return DB_SUCCESS;
2534 }
#define SS_TIMEOUT
Definition: midas.h:680
void ss_stack_history_entry(char *tag)
Definition: system.cxx:7961
INT ss_semaphore_wait_for(HNDLE semaphore_handle, INT timeout)
Definition: system.cxx:2600
INT ss_mutex_wait_for(MUTEX_T *mutex, INT timeout)
Definition: system.cxx:2976
char protect[10][256]
Definition: mana.cxx:251
BOOL inside_lock_unlock
Definition: msystem.h:458
Here is the call graph for this function:

◆ db_merge_data()

INT EXPRT db_merge_data ( HNDLE  hDB,
HNDLE  hKeyRoot,
const char *  name,
void *  data,
INT  data_size,
INT  num_values,
INT  type 
)

Definition at line 7922 of file odb.cxx.

7947 {
7948  HNDLE hKey;
7949  INT status, old_size;
7950 
7951  if (num_values == 0)
7952  return DB_INVALID_PARAM;
7953 
7954  status = db_find_key(hDB, hKeyRoot, name, &hKey);
7955  if (status != DB_SUCCESS) {
7956  db_create_key(hDB, hKeyRoot, name, type);
7957  status = db_find_key(hDB, hKeyRoot, name, &hKey);
7958  if (status != DB_SUCCESS)
7959  return status;
7960  status = db_set_data(hDB, hKey, data, data_size, num_values, type);
7961  } else {
7962  old_size = data_size;
7963  db_get_data(hDB, hKey, data, &old_size, type);
7964  status = db_set_data(hDB, hKey, data, data_size, num_values, type);
7965  }
7966 
7967  return status;
7968 }
INT db_set_data(HNDLE hDB, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type)
Definition: odb.cxx:7209
Here is the call graph for this function:

◆ db_msg()

void db_msg ( db_err_msg **  msg,
INT  message_type,
const char *  filename,
INT  line,
const char *  routine,
const char *  format,
  ... 
)
static

Definition at line 124 of file odb.cxx.

125 {
126  if (!msgp)
127  return;
128 
129  va_list argptr;
130  char message[1000];
131 
132  /* print argument list into message */
133  va_start(argptr, format);
134  vsnprintf(message, sizeof(message)-1, format, argptr);
135  va_end(argptr);
136  message[sizeof(message)-1] = 0; // ensure string is NUL-terminated
137 
138  db_err_msg* msg = new db_err_msg;
139 
140  msg->next = NULL;
141  msg->message_type = message_type;
142  msg->filename = filename;
143  msg->line = line;
144  msg->routine = routine;
145  msg->text = message;
146 
147  _last_error_message = msg;
148 
149  //printf("new message:\n");
150  //db_print_msg(msg);
151 
152  if (*msgp == NULL) {
153  *msgp = msg;
154  return;
155  }
156 
157  // append new message to the end of the list
158  db_err_msg *m = (*msgp);
159  while (m->next != NULL) {
160  m = m->next;
161  }
162  assert(m->next == NULL);
163  m->next = msg;
164 
165  //printf("Message list with added new message:\n");
166  //db_print_msg(*msgp);
167  return;
168 }
static db_err_msg * _last_error_message
Definition: odb.cxx:114
struct db_err_msg_struct db_err_msg
Definition: odb.cxx:72
#define message(type, str)
Definition: midas_macro.h:262
Here is the caller graph for this function:

◆ db_notify_clients()

INT db_notify_clients ( HNDLE  hDB,
HNDLE  hKeyMod,
int  index,
BOOL  bWalk 
)

Definition at line 12598 of file odb.cxx.

12605 {
12606  if (rpc_is_remote()) {
12607  cm_msg(MERROR, "db_notify_clients", "db_notify_clients() does not work in remotely connected MIDAS clients");
12608  return DB_INVALID_HANDLE;
12609  }
12610 
12611 #ifdef LOCAL_ROUTINES
12612  {
12613  db_err_msg* msg = NULL;
12614  int status = db_lock_database(hDB);
12615  if (status != DB_SUCCESS)
12616  return status;
12617  DATABASE_HEADER* pheader = _database[hDB - 1].database_header;
12618  db_notify_clients_locked(pheader, hDB, hKeyMod, index, bWalk, &msg);
12620  if (msg)
12621  db_flush_msg(&msg);
12622  }
12623 #endif
12624  return DB_SUCCESS;
12625 }
static int db_notify_clients_locked(const DATABASE_HEADER *pheader, HNDLE hDB, HNDLE hKeyMod, int index, BOOL bWalk, db_err_msg **msg)
Definition: odb.cxx:12543
Here is the call graph for this function:

◆ db_notify_clients_array()

INT EXPRT db_notify_clients_array ( HNDLE  hDB,
HNDLE  hKeys[],
INT  size 
)

Definition at line 12627 of file odb.cxx.

12639 {
12640  if (rpc_is_remote())
12641  return rpc_call(RPC_DB_NOTIFY_CLIENTS_ARRAY, hDB, hKeys, size);
12642 
12643 #ifdef LOCAL_ROUTINES
12644  {
12645  int status = db_lock_database(hDB);
12646  if (status != DB_SUCCESS)
12647  return status;
12648  db_err_msg* msg = NULL;
12649  DATABASE_HEADER* pheader = _database[hDB - 1].database_header;
12650  int count = size/sizeof(INT);
12651  for (int i=0 ; i<count; i++) {
12652  db_notify_clients_locked(pheader, hDB, hKeys[i], -1, TRUE, &msg);
12653  }
12655  if (msg)
12656  db_flush_msg(&msg);
12657  }
12658 #endif
12659  return DB_SUCCESS;
12660 }
#define RPC_DB_NOTIFY_CLIENTS_ARRAY
Definition: mrpc.h:96
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_notify_clients_locked()

static INT db_notify_clients_locked ( const DATABASE_HEADER pheader,
HNDLE  hDB,
HNDLE  hKeyMod,
int  index,
BOOL  bWalk,
db_err_msg **  msg 
)
static

Definition at line 12543 of file odb.cxx.

12551 {
12552  HNDLE hKey;
12553  KEYLIST *pkeylist;
12554  INT i, j;
12555  char str[80];
12556  int status;
12557 
12558  hKey = hKeyMod;
12559 
12560  const KEY* pkey = db_get_pkey(pheader, hKey, &status, "db_notify_clients", msg);
12561 
12562  if (!pkey) {
12563  return status;
12564  }
12565 
12566  do {
12567 
12568  /* check which client has record open */
12569  if (pkey->notify_count)
12570  for (i = 0; i < pheader->max_client_index; i++) {
12571  const DATABASE_CLIENT* pclient = &pheader->client[i];
12572  for (j = 0; j < pclient->max_index; j++)
12573  if (pclient->open_record[j].handle == hKey) {
12574  /* send notification to remote process */
12575  sprintf(str, "O %d %d %d %d", hDB, hKey, hKeyMod, index);
12576  ss_resume(pclient->port, str);
12577  }
12578  }
12579 
12580  if (pkey->parent_keylist == 0 || !bWalk)
12581  return DB_SUCCESS;
12582 
12583  // FIXME: validate pkey->parent_keylist
12584  pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
12585  pkey = db_get_pkey(pheader, pkeylist->parent, &status, "db_notify_clients", msg);
12586  if (!pkey) {
12587  return status;
12588  }
12589  hKey = db_pkey_to_hkey(pheader, pkey);
12590  } while (TRUE);
12591 
12592 }
INT ss_resume(INT port, const char *message)
Definition: system.cxx:4783
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_open_database()

INT EXPRT db_open_database ( const char *  xdatabase_name,
INT  database_size,
HNDLE hDB,
const char *  client_name 
)

dox Open an online database

Parameters
database_nameDatabase name.
database_sizeInitial size of database if not existing
client_nameName of this application
hDBODB handle obtained via cm_get_experiment_database().
Returns
DB_SUCCESS, DB_CREATED, DB_INVALID_NAME, DB_NO_MEMORY, DB_MEMSIZE_MISMATCH, DB_NO_SEMAPHORE, DB_INVALID_PARAM, RPC_NET_ERROR

Definition at line 1778 of file odb.cxx.

1779 {
1780  if (rpc_is_remote())
1781  return rpc_call(RPC_DB_OPEN_DATABASE, xdatabase_name, database_size, hDB, client_name);
1782 
1783 #ifdef LOCAL_ROUTINES
1784  {
1785  INT i, status;
1786  HNDLE handle;
1787  DATABASE_CLIENT *pclient;
1788  BOOL shm_created;
1789  DATABASE_HEADER *pheader;
1790  KEY *pkey;
1791  KEYLIST *pkeylist;
1792  FREE_DESCRIP *pfree;
1793  BOOL call_watchdog;
1794  DWORD timeout;
1795  char database_name[NAME_LENGTH];
1796 
1797  /* restrict name length */
1798  strlcpy(database_name, xdatabase_name, NAME_LENGTH);
1799 
1800  int odb_size_limit = 100*1000*1000;
1801  if (database_size < 0 || database_size > odb_size_limit) {
1802  cm_msg(MERROR, "db_open_database", "invalid database size: %d bytes. ODB size limit is %d bytes", database_size, odb_size_limit);
1803  return DB_INVALID_PARAM;
1804  }
1805 
1806  if (strlen(client_name) >= NAME_LENGTH) {
1807  cm_msg(MERROR, "db_open_database", "client name \'%s\' is longer than %d characters", client_name, NAME_LENGTH-1);
1808  return DB_INVALID_PARAM;
1809  }
1810 
1811  if (strchr(client_name, '/') != NULL) {
1812  cm_msg(MERROR, "db_open_database", "client name \'%s\' should not contain the slash \'/\' character", client_name);
1813  return DB_INVALID_PARAM;
1814  }
1815 
1816  /* allocate new space for the new database descriptor */
1817  if (_database_entries == 0) {
1818  _database = (DATABASE *) malloc(sizeof(DATABASE));
1819  memset(_database, 0, sizeof(DATABASE));
1820  if (_database == NULL) {
1821  *hDB = 0;
1822  return DB_NO_MEMORY;
1823  }
1824 
1825  _database_entries = 1;
1826  i = 0;
1827  } else {
1828  /* check if database already open */
1829  for (i = 0; i < _database_entries; i++)
1830  if (_database[i].attached && equal_ustring(_database[i].name, database_name)) {
1831  /* check if database belongs to this thread */
1832  *hDB = i + 1;
1833  return DB_SUCCESS;
1834  }
1835 
1836  /* check for a deleted entry */
1837  for (i = 0; i < _database_entries; i++)
1838  if (!_database[i].attached)
1839  break;
1840 
1841  /* if not found, create new one */
1842  if (i == _database_entries) {
1843  _database = (DATABASE *) realloc(_database, sizeof(DATABASE) * (_database_entries + 1));
1844  memset(&_database[_database_entries], 0, sizeof(DATABASE));
1845 
1847  if (_database == NULL) {
1849  *hDB = 0;
1850  return DB_NO_MEMORY;
1851  }
1852  }
1853  }
1854 
1855  handle = (HNDLE) i;
1856 
1857  /* open shared memory region */
1858  void* shm_adr = NULL;
1859  size_t shm_size = 0;
1860  HNDLE shm_handle;
1861 
1862  status = ss_shm_open(database_name, sizeof(DATABASE_HEADER) + 2 * ALIGN8(database_size / 2), &shm_adr, &shm_size, &shm_handle, TRUE);
1863 
1864  if (status == SS_NO_MEMORY || status == SS_FILE_ERROR) {
1865  *hDB = 0;
1866  return DB_INVALID_NAME;
1867  }
1868 
1869  _database[handle].shm_adr = shm_adr;
1870  _database[handle].shm_size = shm_size;
1871  _database[handle].shm_handle = shm_handle;
1872 
1873  _database[handle].database_header = (DATABASE_HEADER *) shm_adr;
1874 
1875  /* shortcut to header */
1876  pheader = _database[handle].database_header;
1877 
1878  /* save name */
1879  strcpy(_database[handle].name, database_name);
1880 
1881  shm_created = (status == SS_CREATED);
1882 
1883  /* clear memeory for debugging */
1884  /* memset(pheader, 0, sizeof(DATABASE_HEADER) + 2*ALIGN8(database_size/2)); */
1885 
1886  if (shm_created && pheader->name[0] == 0) {
1887  /* setup header info if database was created */
1888  memset(pheader, 0, sizeof(DATABASE_HEADER) + 2 * ALIGN8(database_size / 2));
1889 
1890  strcpy(pheader->name, database_name);
1891  pheader->version = DATABASE_VERSION;
1892  pheader->key_size = ALIGN8(database_size / 2);
1893  pheader->data_size = ALIGN8(database_size / 2);
1894  pheader->root_key = sizeof(DATABASE_HEADER);
1895  pheader->first_free_key = sizeof(DATABASE_HEADER);
1896  pheader->first_free_data = sizeof(DATABASE_HEADER) + pheader->key_size;
1897 
1898  /* set up free list */
1899  pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_key);
1900  pfree->size = pheader->key_size;
1901  pfree->next_free = 0;
1902 
1903  pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_data);
1904  pfree->size = pheader->data_size;
1905  pfree->next_free = 0;
1906 
1907  /* create root key */
1908  pkey = (KEY *) malloc_key(pheader, sizeof(KEY), "db_open_database_A");
1909  assert(pkey);
1910 
1911  /* set key properties */
1912  pkey->type = TID_KEY;
1913  pkey->num_values = 1;
1915  strcpy(pkey->name, "root");
1916  pkey->parent_keylist = 0;
1917 
1918  /* create keylist */
1919  pkeylist = (KEYLIST *) malloc_key(pheader, sizeof(KEYLIST), "db_open_database_B");
1920  assert(pkeylist);
1921 
1922  /* store keylist in data field */
1923  pkey->data = (POINTER_T) pkeylist - (POINTER_T) pheader;
1924  pkey->item_size = sizeof(KEYLIST);
1925  pkey->total_size = sizeof(KEYLIST);
1926 
1927  pkeylist->parent = (POINTER_T) pkey - (POINTER_T) pheader;
1928  pkeylist->num_keys = 0;
1929  pkeylist->first_key = 0;
1930  }
1931 
1932  /* check database version */
1933  if (pheader->version != DATABASE_VERSION) {
1934  cm_msg(MERROR, "db_open_database",
1935  "Different database format: Shared memory is %d, program is %d", pheader->version, DATABASE_VERSION);
1936  return DB_VERSION_MISMATCH;
1937  }
1938 
1939  /* check database size vs shared memory size */
1940  if (_database[handle].shm_size < (int)sizeof(DATABASE_HEADER) + pheader->key_size + pheader->data_size) {
1941  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);
1942  return DB_VERSION_MISMATCH;
1943  }
1944 
1945  /* check root key */
1946  if (!db_validate_key_offset(pheader, pheader->root_key)) {
1947  cm_msg(MERROR, "db_open_database", "Invalid, incompatible or corrupted database: root key offset %d is invalid", pheader->root_key);
1948  return DB_VERSION_MISMATCH;
1949  } else {
1950  pkey = (KEY*)((char*)pheader + pheader->root_key);
1951 
1952  if (pkey->type != TID_KEY) {
1953  cm_msg(MERROR, "db_open_database", "Invalid, incompatible or corrupted database: root key type %d is not TID_KEY", pkey->type);
1954  return DB_VERSION_MISMATCH;
1955  }
1956 
1957  if (strcmp(pkey->name, "root") != 0) {
1958  cm_msg(MERROR, "db_open_database", "Invalid, incompatible or corrupted database: root key name \"%s\" is not \"root\"", pkey->name);
1959  return DB_VERSION_MISMATCH;
1960  }
1961 
1962  // what if we are connecting to an incompatible ODB?
1963  // A call to db_validate_and_repair_key() maybe will
1964  // corrupt it here. But we have no choice,
1965  // if we skip it here and continue,
1966  // db_validate_and_repair_db() will call it later anyway... K.O.
1967 
1968  db_err_msg* msg = NULL;
1969  bool ok = db_validate_and_repair_key_wlocked(pheader, 0, "", 0, pheader->root_key, pkey, &msg);
1970  if (msg)
1971  db_flush_msg(&msg);
1972  if (!ok) {
1973  cm_msg(MERROR, "db_open_database", "Invalid, incompatible or corrupted database: root key is invalid");
1974  return DB_VERSION_MISMATCH;
1975  }
1976  }
1977 
1978  /* set default mutex and semaphore timeout */
1979  _database[handle].timeout = 10000;
1980 
1981  /* create mutexes for the database */
1982  status = ss_mutex_create(&_database[handle].mutex, TRUE);
1983  if (status != SS_SUCCESS && status != SS_CREATED) {
1984  *hDB = 0;
1985  return DB_NO_SEMAPHORE;
1986  }
1987 
1988  /* create semaphore for the database */
1989  status = ss_semaphore_create(database_name, &(_database[handle].semaphore));
1990  if (status != SS_SUCCESS && status != SS_CREATED) {
1991  *hDB = 0;
1992  return DB_NO_SEMAPHORE;
1993  }
1994  _database[handle].lock_cnt = 0;
1995 
1996  _database[handle].protect = FALSE;
1997  _database[handle].protect_read = FALSE;
1998  _database[handle].protect_write = FALSE;
1999 
2000  /* first lock database */
2001  status = db_lock_database(handle + 1);
2002  if (status != DB_SUCCESS)
2003  return status;
2004 
2005  /* we have the database locked, without write protection */
2006 
2007  /*
2008  Now we have a DATABASE_HEADER, so let's setup a CLIENT
2009  structure in that database. The information there can also
2010  be seen by other processes.
2011  */
2012 
2013  /*
2014  update the client count
2015  */
2016  int num_clients = 0;
2017  int max_client_index = 0;
2018  for (i = 0; i < MAX_CLIENTS; i++) {
2019  if (pheader->client[i].pid == 0)
2020  continue;
2021  num_clients++;
2022  max_client_index = i + 1;
2023  }
2024  pheader->num_clients = num_clients;
2025  pheader->max_client_index = max_client_index;
2026 
2027  /*fprintf(stderr,"num_clients: %d, max_client: %d\n",pheader->num_clients,pheader->max_client_index); */
2028 
2029  /* remove dead clients */
2030  for (i = 0; i < MAX_CLIENTS; i++) {
2031  if (pheader->client[i].pid == 0)
2032  continue;
2033  if (!ss_pid_exists(pheader->client[i].pid)) {
2034  char client_name_tmp[NAME_LENGTH];
2035  int client_pid;
2036 
2037  strlcpy(client_name_tmp, pheader->client[i].name, sizeof(client_name_tmp));
2038  client_pid = pheader->client[i].pid;
2039 
2040  // removed: /* decrement notify_count for open records and clear exclusive mode */
2041  // open records are corrected later, by db_validate_open_records()
2042 
2043  /* clear entry from client structure in database header */
2044  memset(&(pheader->client[i]), 0, sizeof(DATABASE_CLIENT));
2045 
2046  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);
2047  }
2048  }
2049 
2050  /*
2051  Look for empty client slot
2052  */
2053  for (i = 0; i < MAX_CLIENTS; i++)
2054  if (pheader->client[i].pid == 0)
2055  break;
2056 
2057  if (i == MAX_CLIENTS) {
2058  db_unlock_database(handle + 1);
2059  *hDB = 0;
2060  cm_msg(MERROR, "db_open_database", "maximum number of clients exceeded");
2061  return DB_NO_SLOT;
2062  }
2063 
2064  /* store slot index in _database structure */
2065  _database[handle].client_index = i;
2066 
2067  /*
2068  Save the index of the last client of that database so that later only
2069  the clients 0..max_client_index-1 have to be searched through.
2070  */
2071  pheader->num_clients++;
2072  if (i + 1 > pheader->max_client_index)
2073  pheader->max_client_index = i + 1;
2074 
2075  /* setup database header and client structure */
2076  pclient = &pheader->client[i];
2077 
2078  memset(pclient, 0, sizeof(DATABASE_CLIENT));
2079  strlcpy(pclient->name, client_name, sizeof(pclient->name));
2080  pclient->pid = ss_getpid();
2081  pclient->num_open_records = 0;
2082 
2083  ss_suspend_get_odb_port(&pclient->port);
2084 
2085  pclient->last_activity = ss_millitime();
2086 
2087  cm_get_watchdog_params(&call_watchdog, &timeout);
2088  pclient->watchdog_timeout = timeout;
2089 
2090  /* check ODB for corruption */
2091  db_err_msg* msg = NULL;
2092  bool ok = db_validate_and_repair_db_wlocked(pheader, &msg);
2093  if (msg)
2094  db_flush_msg(&msg);
2095  if (!ok) {
2096  /* do not treat corrupted odb as a fatal error- allow the user
2097  to preceed at own risk- the database is already corrupted,
2098  so no further harm can possibly be made. */
2099  /*
2100  db_unlock_database(handle + 1);
2101  *hDB = 0;
2102  return DB_CORRUPTED;
2103  */
2104  }
2105 
2106  /* setup _database entry */
2107  _database[handle].database_data = _database[handle].database_header + 1;
2108  _database[handle].attached = TRUE;
2109  _database[handle].protect = FALSE;
2110  _database[handle].protect_read = FALSE;
2111  _database[handle].protect_write = FALSE;
2112 
2113  *hDB = (handle + 1);
2114 
2115  status = db_validate_open_records_wlocked(pheader, &msg);
2116  if (status != DB_SUCCESS) {
2117  db_unlock_database(handle + 1);
2118  if (msg)
2119  db_flush_msg(&msg);
2120  cm_msg(MERROR, "db_open_database", "Error: db_validate_open_records() status %d", status);
2121  return status;
2122  }
2123 
2124  db_unlock_database(handle + 1);
2125 
2126  if (msg)
2127  db_flush_msg(&msg);
2128 
2129  if (shm_created)
2130  return DB_CREATED;
2131  }
2132 #endif /* LOCAL_ROUTINES */
2133 
2134  return DB_SUCCESS;
2135 }
INT cm_get_watchdog_params(BOOL *call_watchdog, DWORD *timeout)
Definition: midas.cxx:3313
#define DB_NO_SEMAPHORE
Definition: midas.h:643
#define DB_CREATED
Definition: midas.h:638
#define DB_VERSION_MISMATCH
Definition: midas.h:662
#define DB_NO_SLOT
Definition: midas.h:642
#define SS_FILE_ERROR
Definition: midas.h:675
#define SS_NO_MEMORY
Definition: midas.h:671
#define SS_CREATED
Definition: midas.h:670
#define ALIGN8(x)
Definition: midas.h:528
INT ss_suspend_get_odb_port(INT *port)
Definition: system.cxx:4266
INT ss_semaphore_create(const char *name, HNDLE *semaphore_handle)
Definition: system.cxx:2427
INT ss_mutex_create(MUTEX_T **mutex, BOOL recursive)
Definition: system.cxx:2880
INT ss_shm_open(const char *name, INT size, void **adr, size_t *shm_size, HNDLE *handle, BOOL get_size)
Definition: system.cxx:333
static bool db_validate_and_repair_db_wlocked(DATABASE_HEADER *pheader, db_err_msg **msg)
Definition: odb.cxx:1650
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)
Definition: odb.cxx:1148
static int db_validate_open_records_wlocked(DATABASE_HEADER *pheader, db_err_msg **msg)
Definition: odb.cxx:1587
#define RPC_DB_OPEN_DATABASE
Definition: mrpc.h:52
#define DATABASE_VERSION
Definition: midas.h:34
void * database_data
Definition: msystem.h:447
INT timeout
Definition: msystem.h:457
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_open_record()

INT EXPRT db_open_record ( HNDLE  hDB,
HNDLE  hKey,
void *  ptr,
INT  rec_size,
WORD  access_mode,
void(*)(INT, INT, void *)  dispatcher,
void *  info 
)

Open a record. Create a local copy and maintain an automatic update.

This function opens a hot-link between an ODB sub-tree and a local structure. The sub-tree is copied to the structure automatically every time it is modified by someone else. Additionally, a callback function can be declared which is called after the structure has been updated. The callback function receives the database handle and the key handle as parameters.

Problems might occur if the ODB sub-tree contains values which don't match the C structure. Although the structure size is checked against the sub-tree size, no checking can be done if the type and order of the values in the structure are the same than those in the ODB sub-tree. Therefore it is recommended to use the function db_create_record() before db_open_record() is used which ensures that both are equivalent.

The access mode might either be MODE_READ or MODE_WRITE. In read mode, the ODB sub-tree is automatically copied to the local structure when modified by other clients. In write mode, the local structure is copied to the ODB sub-tree if it has been modified locally. This update has to be manually scheduled by calling db_send_changed_records() periodically in the main loop. The system keeps a copy of the local structure to determine if its contents has been changed.

If MODE_ALLOC is or'ed with the access mode, the memory for the structure is allocated internally. The structure pointer must contain a pointer to a pointer to the structure. The internal memory is released when db_close_record() is called.

Definition at line 13294 of file odb.cxx.

13296 {
13297  INT idx, status, size;
13298  KEY key;
13299  void *data;
13300  char str[256];
13301 
13302  /* allocate new space for the local record list */
13303  if (_record_list_entries == 0) {
13304  _record_list = (RECORD_LIST *) malloc(sizeof(RECORD_LIST));
13305  memset(_record_list, 0, sizeof(RECORD_LIST));
13306  if (_record_list == NULL) {
13307  cm_msg(MERROR, "db_open_record", "not enough memory");
13308  return DB_NO_MEMORY;
13309  }
13310 
13312  idx = 0;
13313  } else {
13314  /* check for a deleted entry */
13315  for (idx = 0; idx < _record_list_entries; idx++)
13316  if (!_record_list[idx].handle)
13317  break;
13318 
13319  /* if not found, create new one */
13320  if (idx == _record_list_entries) {
13321  _record_list = (RECORD_LIST *) realloc(_record_list, sizeof(RECORD_LIST) * (_record_list_entries + 1));
13322  if (_record_list == NULL) {
13323  cm_msg(MERROR, "db_open_record", "not enough memory");
13324  return DB_NO_MEMORY;
13325  }
13326 
13327  memset(&_record_list[_record_list_entries], 0, sizeof(RECORD_LIST));
13328 
13330  }
13331  }
13332 
13333  db_get_key(hDB, hKey, &key);
13334 
13335  /* check record size */
13336  status = db_get_record_size(hDB, hKey, 0, &size);
13337  if (status != DB_SUCCESS) {
13339  cm_msg(MERROR, "db_open_record", "cannot get record size, db_get_record_size() status %d", status);
13340  return DB_NO_MEMORY;
13341  }
13342 
13343  if (size != rec_size && ptr != NULL) {
13345  db_get_path(hDB, hKey, str, sizeof(str));
13346  cm_msg(MERROR, "db_open_record", "struct size mismatch for \"%s\" (expected size: %d, size in ODB: %d)", str, rec_size, size);
13347  return DB_STRUCT_SIZE_MISMATCH;
13348  }
13349 
13350  /* check for read access */
13351  if (((key.access_mode & MODE_EXCLUSIVE) && (access_mode & MODE_WRITE))
13352  || (!(key.access_mode & MODE_WRITE) && (access_mode & MODE_WRITE))
13353  || (!(key.access_mode & MODE_READ) && (access_mode & MODE_READ))) {
13355  return DB_NO_ACCESS;
13356  }
13357 
13358  if (access_mode & MODE_ALLOC) {
13359  data = malloc(size);
13360 
13361  if (data == NULL) {
13363  cm_msg(MERROR, "db_open_record", "not enough memory, malloc(%d) returned NULL", size);
13364  return DB_NO_MEMORY;
13365  }
13366 
13367  memset(data, 0, size);
13368 
13369  *((void **) ptr) = data;
13370  } else {
13371  data = ptr;
13372  }
13373 
13374  /* copy record to local memory */
13375  if (access_mode & MODE_READ && data != NULL) {
13376  status = db_get_record(hDB, hKey, data, &size, 0);
13377  if (status != DB_SUCCESS) {
13379  cm_msg(MERROR, "db_open_record", "cannot get record, db_get_record() status %d", status);
13380  return DB_NO_MEMORY;
13381  }
13382  }
13383 
13384  /* copy local record to ODB */
13385  if (access_mode & MODE_WRITE) {
13386  /* only write to ODB if not in MODE_ALLOC */
13387  if ((access_mode & MODE_ALLOC) == 0) {
13388  status = db_set_record(hDB, hKey, data, size, 0);
13389  if (status != DB_SUCCESS) {
13391  cm_msg(MERROR, "db_open_record", "cannot set record, db_set_record() status %d", status);
13392  return DB_NO_MEMORY;
13393  }
13394  }
13395 
13396  /* init a local copy of the record */
13397  _record_list[idx].copy = malloc(size);
13398  if (_record_list[idx].copy == NULL) {
13399  cm_msg(MERROR, "db_open_record", "not enough memory");
13400  return DB_NO_MEMORY;
13401  }
13402 
13403  memcpy(_record_list[idx].copy, data, size);
13404  }
13405 
13406  /* initialize record list */
13407  _record_list[idx].handle = hKey;
13408  _record_list[idx].hDB = hDB;
13409  _record_list[idx].access_mode = access_mode;
13410  _record_list[idx].data = data;
13411  _record_list[idx].buf_size = size;
13412  _record_list[idx].dispatcher = dispatcher;
13413  _record_list[idx].info = info;
13414 
13415  /* add record entry in database structure */
13416  return db_add_open_record(hDB, hKey, (WORD) (access_mode & ~MODE_ALLOC));
13417 }
INT db_set_record(HNDLE hDB, HNDLE hKey, void *data, INT buf_size, INT align)
Definition: odb.cxx:12295
INT db_add_open_record(HNDLE hDB, HNDLE hKey, WORD access_mode)
Definition: odb.cxx:12367
WORD access_mode
Definition: msystem.h:467
void(* dispatcher)(INT, INT, void *)
Definition: msystem.h:471
void * info
Definition: msystem.h:472
INT buf_size
Definition: msystem.h:470
HNDLE handle
Definition: msystem.h:465
HNDLE hDB
Definition: msystem.h:466
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_open_record1()

INT EXPRT db_open_record1 ( HNDLE  hDB,
HNDLE  hKey,
void *  ptr,
INT  rec_size,
WORD  access_mode,
void(*)(INT, INT, void *)  dispatcher,
void *  info,
const char *  rec_str 
)

Open a record. Create a local copy and maintain an automatic update.

This function is same as db_open_record(), except that it calls db_check_record(), db_get_record1() and db_create_record() to ensure that the ODB structure matches

Parameters are the same as for db_open_record():

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
ptrIf access_mode includes MODE_ALLOC: Address of pointer which points to the record data after the call if access_mode includes not MODE_ALLOC: Address of record if ptr==NULL, only the dispatcher is called.
rec_sizeRecord size in bytes
access_modeMode for opening record, either MODE_READ or MODE_WRITE. May be or'ed with MODE_ALLOC to let db_open_record allocate the memory for the record.
(*dispatcher)Function which gets called when record is updated.The argument list composed of: HNDLE hDB, HNDLE hKey, void *info
infoAdditional info passed to the dispatcher.
rec_strASCII representation of ODB record in the format
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_NO_MEMORY, DB_NO_ACCESS, DB_STRUCT_SIZE_MISMATCH

Definition at line 13445 of file odb.cxx.

13448 {
13449  if (rec_str) {
13450  int status;
13451  if (rec_size) {
13452  char* pbuf;
13453  int size = rec_size;
13454  pbuf = (char*)malloc(size);
13455  assert(pbuf != NULL);
13456  status = db_get_record1(hDB, hKey, pbuf, &size, 0, rec_str);
13457  free(pbuf);
13458  if (status != DB_SUCCESS)
13459  return status;
13460  }
13461 
13462  status = db_check_record(hDB, hKey, "", rec_str, TRUE);
13463  if (status != DB_SUCCESS)
13464  return status;
13465  }
13466 
13467  return db_open_record(hDB, hKey, ptr, rec_size, access_mode, dispatcher, info);
13468 }
INT db_get_record1(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT align, const char *rec_str)
Definition: odb.cxx:11809
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_parse_record()

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 
)
static

Definition at line 11870 of file odb.cxx.

11871 {
11872  title[0] = 0;
11873  key_name[0] = 0;
11874  *tid = 0;
11875  *n_data = 0;
11876  *string_length = 0;
11877  *out_rec_str = NULL;
11878 
11879  //
11880  // expected format of rec_str:
11881  //
11882  // title: "[.]",
11883  // numeric value: "example_int = INT : 3",
11884  // string value: "example_string = STRING : [20] /Runinfo/Run number",
11885  // array: "aaa = INT[10] : ...",
11886  // string array: "sarr = STRING[10] : [32] ",
11887  //
11888 
11889  //printf("parse_rec_str: [%s]\n", rec_str);
11890 
11891  while (*rec_str == '\n')
11892  rec_str++;
11893 
11894  /* check if it is a section title */
11895  if (rec_str[0] == '[') {
11896  rec_str++;
11897 
11898  title[0] = 0;
11899 
11900  /* extract title and append '/' */
11901  strlcpy(title, rec_str, title_size);
11902  char* p = strchr(title, ']');
11903  if (p)
11904  *p = 0;
11905 
11906  int len = strlen(title);
11907  if (len > 0) {
11908  if (title[len - 1] != '/')
11909  strlcat(title, "/", title_size);
11910  }
11911 
11912  // skip to the next end-of-line
11913  const char* pend = strchr(rec_str, '\n');
11914  if (pend)
11915  rec_str = pend;
11916  else
11917  rec_str = rec_str+strlen(rec_str);
11918 
11919  while (*rec_str == '\n')
11920  rec_str++;
11921 
11922  *out_rec_str = rec_str;
11923  return DB_SUCCESS;
11924  }
11925 
11926  if (rec_str[0] == ';') {
11927  // skip to the next end-of-line
11928  const char* pend = strchr(rec_str, '\n');
11929  if (pend)
11930  rec_str = pend;
11931  else
11932  rec_str = rec_str+strlen(rec_str);
11933 
11934  while (*rec_str == '\n')
11935  rec_str++;
11936 
11937  *out_rec_str = rec_str;
11938  return DB_SUCCESS;
11939  }
11940 
11941  const char* peq = strchr(rec_str, '=');
11942  if (!peq) {
11943  cm_msg(MERROR, "db_parse_record", "do not see \'=\'");
11944  return DB_INVALID_PARAM;
11945  }
11946 
11947  int key_name_len = peq - rec_str;
11948 
11949  // remove trailing equals sign and trailing spaces
11950  while (key_name_len > 1) {
11951  if (rec_str[key_name_len-1] == '=') {
11952  key_name_len--;
11953  continue;
11954  }
11955  if (rec_str[key_name_len-1] == ' ') {
11956  key_name_len--;
11957  continue;
11958  }
11959  break;
11960  }
11961 
11962  memcpy(key_name, rec_str, key_name_len);
11963  key_name[key_name_len] = 0;
11964 
11965  rec_str = peq + 1; // consume the "=" sign
11966 
11967  while (*rec_str == ' ') // consume spaces
11968  rec_str++;
11969 
11970  // extract type id
11971  char stid[256];
11972  int i;
11973  for (i=0; i<(int)sizeof(stid)-1; i++) {
11974  char s = *rec_str;
11975  if (s == 0) break;
11976  if (s == ' ') break;
11977  if (s == '\n') break;
11978  if (s == '[') break;
11979  stid[i] = s;
11980  rec_str++;
11981  }
11982  stid[i] = 0;
11983 
11984  DWORD xtid = 0;
11985  for (xtid = 0; xtid < TID_LAST; xtid++) {
11986  if (strcmp(rpc_tid_name(xtid), stid) == 0) {
11987  *tid = xtid;
11988  break;
11989  }
11990  }
11991 
11992  //printf("tid [%s], tid %d\n", stid, *tid);
11993 
11994  if (xtid == TID_LAST) {
11995  cm_msg(MERROR, "db_parse_record", "do not see \':\'");
11996  return DB_INVALID_PARAM;
11997  }
11998 
11999  while (*rec_str == ' ') // consume spaces
12000  rec_str++;
12001 
12002  *n_data = 1;
12003 
12004  if (*rec_str == '[') {
12005  // decode array size
12006  rec_str++; // cosume the '['
12007  *n_data = atoi(rec_str);
12008  const char *pbr = strchr(rec_str, ']');
12009  if (!pbr) {
12010  cm_msg(MERROR, "db_parse_record", "do not see closing bracket \']\'");
12011  return DB_INVALID_PARAM;
12012  }
12013  rec_str = pbr + 1; // skip the closing bracket
12014  }
12015 
12016  while (*rec_str == ' ') // consume spaces
12017  rec_str++;
12018 
12019  const char* pcol = strchr(rec_str, ':');
12020  if (!pcol) {
12021  cm_msg(MERROR, "db_parse_record", "do not see \':\'");
12022  return DB_INVALID_PARAM;
12023  }
12024 
12025  rec_str = pcol + 1; // skip the ":"
12026 
12027  while (*rec_str == ' ') // consume spaces
12028  rec_str++;
12029 
12030  *string_length = 0;
12031  if (xtid == TID_LINK || xtid == TID_STRING) {
12032  // extract string length
12033  const char* pbr = strchr(rec_str, '[');
12034  if (pbr) {
12035  *string_length = atoi(pbr+1);
12036  }
12037  }
12038 
12039  // skip to the next end-of-line
12040  const char* pend = strchr(rec_str, '\n');
12041  if (pend)
12042  rec_str = pend;
12043  else
12044  rec_str = rec_str+strlen(rec_str);
12045 
12046  while (*rec_str == '\n')
12047  rec_str++;
12048 
12049  *out_rec_str = rec_str;
12050  return DB_SUCCESS;
12051 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_paste()

INT EXPRT db_paste ( HNDLE  hDB,
HNDLE  hKeyRoot,
const char *  buffer 
)

Copy an ODB subtree in ASCII format from a buffer

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyRootHandle for key where search starts, zero for root.
bufferNULL-terminated buffer
Returns
DB_SUCCESS, DB_TRUNCATED, DB_NO_MEMORY

Definition at line 8487 of file odb.cxx.

8488 {
8489  char title[MAX_STRING_LENGTH];
8490  char *data;
8491  const char *pold;
8492  INT data_size, index;
8493  INT tid, i, j, n_data, string_length, status, size;
8494  HNDLE hKey;
8495  KEY root_key;
8496 
8497  title[0] = 0;
8498 
8499  if (hKeyRoot == 0)
8500  db_find_key(hDB, hKeyRoot, "", &hKeyRoot);
8501 
8502  db_get_key(hDB, hKeyRoot, &root_key);
8503 
8504  /* initial data size */
8505  data_size = 1000;
8506  data = (char *) malloc(data_size);
8507  if (data == NULL) {
8508  cm_msg(MERROR, "db_paste", "cannot allocate data buffer");
8509  return DB_NO_MEMORY;
8510  }
8511 
8512  do {
8513  char line[10*MAX_STRING_LENGTH];
8514 
8515  if (*buffer == 0)
8516  break;
8517 
8518  for (i = 0; *buffer != '\n' && *buffer && i < 10*MAX_STRING_LENGTH; i++)
8519  line[i] = *buffer++;
8520 
8521  if (i == 10*MAX_STRING_LENGTH) {
8522  line[10*MAX_STRING_LENGTH-1] = 0;
8523  cm_msg(MERROR, "db_paste", "line too long: %s...", line);
8524  free(data);
8525  return DB_TRUNCATED;
8526  }
8527 
8528  line[i] = 0;
8529  if (*buffer == '\n')
8530  buffer++;
8531 
8532  /* check if it is a section title */
8533  if (line[0] == '[') {
8534  /* extract title and append '/' */
8535  strlcpy(title, line + 1, sizeof(title));
8536  if (strchr(title, ']'))
8537  *strchr(title, ']') = 0;
8538  if (title[0] && title[strlen(title) - 1] != '/')
8539  strlcat(title, "/", sizeof(title));
8540  } else {
8541  /* valid data line if it includes '=' and no ';' */
8542  if (strchr(line, '=') && line[0] != ';') {
8543  char key_name[MAX_ODB_PATH];
8544  char test_str[MAX_ODB_PATH];
8545  char data_str[10*MAX_STRING_LENGTH];
8546 
8547  /* copy type info and data */
8548  char* pline = strrchr(line, '=') + 1;
8549  while (strstr(line, ": [") != NULL && strstr(line, ": [") < pline) {
8550  pline -= 2;
8551  while (*pline != '=' && pline > line)
8552  pline--;
8553  pline++;
8554  }
8555  while (*pline == ' ')
8556  pline++;
8557  strlcpy(data_str, pline, sizeof(data_str));
8558 
8559  /* extract key name */
8560  *strrchr(line, '=') = 0;
8561  while (strstr(line, ": [") && strchr(line, '='))
8562  *strrchr(line, '=') = 0;
8563 
8564  pline = &line[strlen(line) - 1];
8565  while (*pline == ' ')
8566  *pline-- = 0;
8567 
8568  key_name[0] = 0;
8569  if (title[0] != '.')
8570  strlcpy(key_name, title, sizeof(key_name));
8571 
8572  strlcat(key_name, line, sizeof(key_name));
8573 
8574  /* evaluate type info */
8575  strlcpy(line, data_str, sizeof(line));
8576  if (strchr(line, ' '))
8577  *strchr(line, ' ') = 0;
8578 
8579  n_data = 1;
8580  if (strchr(line, '[')) {
8581  n_data = atol(strchr(line, '[') + 1);
8582  *strchr(line, '[') = 0;
8583  }
8584 
8585  for (tid = 0; tid < TID_LAST; tid++)
8586  if (strcmp(rpc_tid_name(tid), line) == 0)
8587  break;
8588  if (tid == TID_LAST) {
8589  for (tid = 0; tid < TID_LAST; tid++)
8590  if (strcmp(rpc_tid_name_old(tid), line) == 0)
8591  break;
8592  }
8593 
8594  string_length = 0;
8595 
8596  if (tid == TID_LAST)
8597  cm_msg(MERROR, "db_paste", "found unknown data type \"%s\" in ODB file", line);
8598  else {
8599  /* skip type info */
8600  char* pc = data_str;
8601  while (*pc != ' ' && *pc)
8602  pc++;
8603  while ((*pc == ' ' || *pc == ':') && *pc)
8604  pc++;
8605 
8606  //strlcpy(data_str, pc, sizeof(data_str)); // MacOS 10.9 does not permit strlcpy() of overlapping strings
8607  assert(strlen(pc) < sizeof(data_str)); // "pc" points at a substring inside "data_str"
8608  memmove(data_str, pc, strlen(pc)+1);
8609 
8610  if (n_data > 1) {
8611  data_str[0] = 0;
8612  if (!*buffer)
8613  break;
8614 
8615  for (j = 0; *buffer != '\n' && *buffer; j++)
8616  data_str[j] = *buffer++;
8617  data_str[j] = 0;
8618  if (*buffer == '\n')
8619  buffer++;
8620  }
8621 
8622  for (i = 0; i < n_data; i++) {
8623  /* strip trailing \n */
8624  char* pc = &data_str[strlen(data_str) - 1];
8625  while (*pc == '\n' || *pc == '\r')
8626  *pc-- = 0;
8627 
8628  if (tid == TID_STRING || tid == TID_LINK) {
8629  if (!string_length) {
8630  if (data_str[1] == '=')
8631  string_length = -1;
8632  else
8633  string_length = atoi(data_str + 1);
8634  if (string_length > MAX_STRING_LENGTH) {
8635  string_length = MAX_STRING_LENGTH;
8636  cm_msg(MERROR, "db_paste", "found string exceeding MAX_STRING_LENGTH, odb path \"%s\"", key_name);
8637  }
8638  if (string_length == 0) {
8639  string_length = 32;
8640  cm_msg(MERROR, "db_paste", "found string length of zero, set to 32, odb path \"%s\"", key_name);
8641  }
8642  }
8643 
8644  if (string_length == -1) {
8645  /* multi-line string */
8646  if (strstr(buffer, "\n====#$@$#====\n") != NULL) {
8647  string_length = (POINTER_T) strstr(buffer, "\n====#$@$#====\n") - (POINTER_T) buffer + 1;
8648 
8649  if (string_length >= data_size) {
8650  data_size += string_length + 100;
8651  data = (char *) realloc(data, data_size);
8652  if (data == NULL) {
8653  cm_msg(MERROR, "db_paste", "cannot allocate data buffer");
8654  return DB_NO_MEMORY;
8655  }
8656  }
8657 
8658  memset(data, 0, data_size);
8659  strncpy(data, buffer, string_length);
8660  data[string_length - 1] = 0;
8661  buffer = strstr(buffer, "\n====#$@$#====\n") + strlen("\n====#$@$#====\n");
8662  } else
8663  cm_msg(MERROR, "db_paste", "found multi-line string without termination sequence");
8664  } else {
8665  char* pc = data_str + 2;
8666  while (*pc && *pc != ' ')
8667  pc++;
8668 
8669  // skip one space (needed for strings starting with spaces)
8670  if (*pc)
8671  pc++;
8672 
8673  /* limit string size */
8674  *(pc + string_length - 1) = 0;
8675 
8676  /* increase data buffer if necessary */
8677  if (string_length * (i + 1) >= data_size) {
8678  data_size += 1000;
8679  data = (char *) realloc(data, data_size);
8680  if (data == NULL) {
8681  cm_msg(MERROR, "db_paste", "cannot allocate data buffer");
8682  return DB_NO_MEMORY;
8683  }
8684  }
8685 
8686  strlcpy(data + string_length * i, pc, string_length);
8687  }
8688  } else {
8689  char* pc = data_str;
8690 
8691  if (n_data > 1 && data_str[0] == '[') {
8692  index = atoi(data_str+1);
8693  pc = strchr(data_str, ']') + 1;
8694  while (*pc && *pc == ' ')
8695  pc++;
8696  } else
8697  index = 0;
8698 
8699  /* increase data buffer if necessary */
8700  if (rpc_tid_size(tid) * (index + 1) >= data_size) {
8701  data_size += 1000;
8702  data = (char *) realloc(data, data_size);
8703  if (data == NULL) {
8704  cm_msg(MERROR, "db_paste", "cannot allocate data buffer");
8705  return DB_NO_MEMORY;
8706  }
8707  }
8708 
8709  db_sscanf(pc, data, &size, index, tid);
8710  }
8711 
8712  if (i < n_data - 1) {
8713  data_str[0] = 0;
8714  if (!*buffer)
8715  break;
8716 
8717  pold = buffer;
8718 
8719  for (j = 0; *buffer != '\n' && *buffer; j++)
8720  data_str[j] = *buffer++;
8721  data_str[j] = 0;
8722  if (*buffer == '\n')
8723  buffer++;
8724 
8725  /* test if valid data */
8726  if (tid != TID_STRING && tid != TID_LINK) {
8727  if (data_str[0] == 0 || (strchr(data_str, '=')
8728  && strchr(data_str, ':')))
8729  buffer = pold;
8730  }
8731  }
8732  }
8733 
8734  /* skip system client entries */
8735  strlcpy(test_str, key_name, sizeof(test_str));
8736  test_str[15] = 0;
8737 
8738  if (!equal_ustring(test_str, "/System/Clients")) {
8739  if (root_key.type != TID_KEY) {
8740  /* root key is destination key */
8741  hKey = hKeyRoot;
8742  } else {
8743  /* create key and set value */
8744  if (key_name[0] == '/') {
8745  status = db_find_link(hDB, 0, key_name, &hKey);
8746  if (status == DB_NO_KEY) {
8747  db_create_key(hDB, 0, key_name, tid);
8748  status = db_find_link(hDB, 0, key_name, &hKey);
8749  }
8750  } else {
8751  status = db_find_link(hDB, hKeyRoot, key_name, &hKey);
8752  if (status == DB_NO_KEY) {
8753  db_create_key(hDB, hKeyRoot, key_name, tid);
8754  status = db_find_link(hDB, hKeyRoot, key_name, &hKey);
8755  }
8756  }
8757  }
8758 
8759  /* set key data if created successfully */
8760  if (hKey) {
8761  if (tid == TID_STRING || tid == TID_LINK)
8762  db_set_link_data(hDB, hKey, data, string_length * n_data, n_data, tid);
8763  else
8764  db_set_link_data(hDB, hKey, data, rpc_tid_size(tid) * n_data, n_data, tid);
8765  }
8766  }
8767  }
8768  }
8769  }
8770  } while (TRUE);
8771 
8772  free(data);
8773  return DB_SUCCESS;
8774 }
INT db_sscanf(const char *data_str, void *data, INT *data_size, INT i, DWORD tid)
Definition: odb.cxx:11318
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_paste_json()

INT EXPRT db_paste_json ( HNDLE  hDB,
HNDLE  hKey,
const char *  buffer 
)

Definition at line 691 of file json_paste.cxx.

692 {
693  int status;
694  char path[MAX_ODB_PATH];
695 
696  status = db_get_path(hDB, hKeyRoot, path, sizeof(path));
697 
698  //printf("db_paste_json: handle %d, path [%s]\n", hKeyRoot, path);
699 
700  MJsonNode* node = MJsonNode::Parse(buffer);
701  status = paste_node(hDB, hKeyRoot, path, false, 0, node, 0, 0, NULL);
702  delete node;
703 
704  return status;
705 }
static int paste_node(HNDLE hDB, HNDLE hKey, const char *path, bool is_array, int index, const MJsonNode *node, int tid, int string_length, const MJsonNode *key)
Definition: json_paste.cxx:668
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_paste_json_node()

INT EXPRT db_paste_json_node ( HNDLE  hDB,
HNDLE  hKey,
int  index,
const MJsonNode *  json_node 
)

Definition at line 707 of file json_paste.cxx.

708 {
709  int status;
710  char path[MAX_ODB_PATH];
711  KEY key;
712 
713  status = db_get_key(hDB, hKeyRoot, &key);
714  if (status != DB_SUCCESS)
715  return status;
716 
717  status = db_get_path(hDB, hKeyRoot, path, sizeof(path));
718  if (status != DB_SUCCESS)
719  return status;
720 
721  int tid = key.type;
722  int string_length = 0;
723  bool is_array = (key.num_values > 1);
724  if (tid == TID_STRING) {
725  // do not truncate strings, only extend if necessary
726  if ((int)node->GetString().length()+1 > key.item_size)
727  string_length = node->GetString().length()+1;
728  else
729  string_length = key.item_size;
730  }
731 
732  status = paste_node(hDB, hKeyRoot, path, is_array, index, node, tid, string_length, NULL);
733 
734  return status;
735 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_paste_node()

static int db_paste_node ( HNDLE  hDB,
HNDLE  hKeyRoot,
PMXML_NODE  node 
)
static

Definition at line 8780 of file odb.cxx.

8781 {
8782  int status;
8783 
8784  if (strcmp(mxml_get_name(node), "odb") == 0) {
8785  for (int i = 0; i < mxml_get_number_of_children(node); i++) {
8786  status = db_paste_node(hDB, hKeyRoot, mxml_subnode(node, i));
8787  if (status != DB_SUCCESS)
8788  return status;
8789  }
8790  } else if (strcmp(mxml_get_name(node), "dir") == 0) {
8791  const char* name = mxml_get_attribute(node, "name");
8792 
8793  if (name == NULL) {
8794  cm_msg(MERROR, "db_paste_node", "found key \"%s\" with no name in XML data", mxml_get_name(node));
8795  return DB_TYPE_MISMATCH;
8796  }
8797 
8798  HNDLE hKey;
8799  status = db_find_link(hDB, hKeyRoot, name, &hKey);
8800 
8801  if (status == DB_NO_KEY) {
8802  status = db_create_key(hDB, hKeyRoot, name, TID_KEY);
8803  if (status == DB_NO_ACCESS) {
8804  cm_msg(MINFO, "db_paste_node", "cannot load key \"%s\": write protected", name);
8805  return DB_SUCCESS; /* key or tree is locked, just skip it */
8806  }
8807 
8808  if (status != DB_SUCCESS && status != DB_KEY_EXIST) {
8809  cm_msg(MERROR, "db_paste_node", "cannot create key \"%s\" in ODB, status = %d", name, status);
8810  return status;
8811  }
8812  status = db_find_link(hDB, hKeyRoot, name, &hKey);
8813  if (status != DB_SUCCESS) {
8814  cm_msg(MERROR, "db_paste_node", "cannot find key \"%s\" in ODB", name);
8815  return status;
8816  }
8817  }
8818 
8819  std::string path = db_get_path(hDB, hKey);
8820  if (!equal_ustring(path.c_str(), "/System/Clients")) {
8821  for (int i = 0; i < mxml_get_number_of_children(node); i++) {
8822  status = db_paste_node(hDB, hKey, mxml_subnode(node, i));
8823  if (status != DB_SUCCESS)
8824  return status;
8825  }
8826  }
8827  } else if (strcmp(mxml_get_name(node), "key") == 0 || strcmp(mxml_get_name(node), "keyarray") == 0) {
8828 
8829  const char* name = mxml_get_attribute(node, "name");
8830 
8831  if (name == NULL) {
8832  cm_msg(MERROR, "db_paste_node", "found key \"%s\" with no name in XML data", mxml_get_name(node));
8833  return DB_TYPE_MISMATCH;
8834  }
8835 
8836  int num_values;
8837  if (strcmp(mxml_get_name(node), "keyarray") == 0)
8838  num_values = atoi(mxml_get_attribute(node, "num_values"));
8839  else
8840  num_values = 0;
8841 
8842  const char* type = mxml_get_attribute(node, "type");
8843 
8844  if (type == NULL) {
8845  cm_msg(MERROR, "db_paste_node", "found key \"%s\" with no type in XML data", mxml_get_name(node));
8846  return DB_TYPE_MISMATCH;
8847  }
8848 
8849  int tid = rpc_name_tid(type);
8850  if (tid == 0) {
8851  cm_msg(MERROR, "db_paste_node", "found unknown data type \"%s\" in XML data", type);
8852  return DB_TYPE_MISMATCH;
8853  }
8854 
8855  HNDLE hKey;
8856  status = db_find_link(hDB, hKeyRoot, name, &hKey);
8857  if (status == DB_NO_KEY) {
8858  status = db_create_key(hDB, hKeyRoot, name, tid);
8859  if (status == DB_NO_ACCESS) {
8860  cm_msg(MINFO, "db_paste_node", "cannot load key \"%s\": write protected", name);
8861  return DB_SUCCESS; /* key or tree is locked, just skip it */
8862  }
8863 
8864  if (status != DB_SUCCESS) {
8865  cm_msg(MERROR, "db_paste_node", "cannot create key \"%s\" in ODB, status = %d", name, status);
8866  return status;
8867  }
8868  status = db_find_link(hDB, hKeyRoot, name, &hKey);
8869  if (status != DB_SUCCESS) {
8870  cm_msg(MERROR, "db_paste_node", "cannot find key \"%s\" in ODB, status = %d", name, status);
8871  return status;
8872  }
8873  } else {
8874  KEY key;
8875  status = db_get_key(hDB, hKey, &key);
8876  if (status != DB_SUCCESS) {
8877  cm_msg(MERROR, "db_paste_node", "cannot get key \"%s\" in ODB, status = %d", name, status);
8878  return status;
8879  }
8880 
8881  if (num_values > 0 && num_values != key.num_values && key.item_size > 0) {
8882  status = db_set_num_values(hDB, hKey, num_values);
8883  if (status != DB_SUCCESS) {
8884  cm_msg(MERROR, "db_paste_node", "cannot resize key \"%s\" in ODB, status = %d", name, status);
8885  return status;
8886  }
8887  }
8888  }
8889 
8890  int size = 0;
8891  char *buf = NULL;
8892 
8893  if (tid == TID_STRING || tid == TID_LINK) {
8894  size = atoi(mxml_get_attribute(node, "size"));
8895  buf = (char *)malloc(size);
8896  assert(buf);
8897  buf[0] = 0;
8898  }
8899 
8900  if (num_values) {
8901  /* evaluate array */
8902  for (int i = 0; i < mxml_get_number_of_children(node); i++) {
8903  PMXML_NODE child = mxml_subnode(node, i);
8904  int idx;
8905  if (mxml_get_attribute(child, "index"))
8906  idx = atoi(mxml_get_attribute(child, "index"));
8907  else
8908  idx = i;
8909  if (tid == TID_STRING || tid == TID_LINK) {
8910  if (mxml_get_value(child) == NULL) {
8911  status = db_set_data_index(hDB, hKey, "", size, i, tid);
8912  if (status == DB_NO_ACCESS) {
8913  cm_msg(MINFO, "db_paste_node", "cannot load string or link \"%s\": write protected", mxml_get_attribute(node, "name"));
8914  return DB_SUCCESS; /* key or tree is locked, just skip it */
8915  } else if (status != DB_SUCCESS) {
8916  cm_msg(MERROR, "db_paste_node", "cannot load string or link \"%s\": db_set_data_index() status %d", mxml_get_attribute(node, "name"), status);
8917  return status;
8918  }
8919  } else {
8920  strlcpy(buf, mxml_get_value(child), size);
8921  status = db_set_data_index(hDB, hKey, buf, size, idx, tid);
8922  if (status == DB_NO_ACCESS) {
8923  cm_msg(MINFO, "db_paste_node", "cannot load array element \"%s\": write protected", mxml_get_attribute(node, "name"));
8924  return DB_SUCCESS; /* key or tree is locked, just skip it */
8925  } else if (status != DB_SUCCESS) {
8926  cm_msg(MERROR, "db_paste_node", "cannot load array element \"%s\": db_set_data_index() status %d", mxml_get_attribute(node, "name"), status);
8927  return status;
8928  }
8929  }
8930  } else {
8931  char data[256];
8932  db_sscanf(mxml_get_value(child), data, &size, 0, tid);
8933  status = db_set_data_index(hDB, hKey, data, rpc_tid_size(tid), idx, tid);
8934  if (status == DB_NO_ACCESS) {
8935  cm_msg(MINFO, "db_paste_node", "cannot load array element \"%s\": write protected", mxml_get_attribute(node, "name"));
8936  return DB_SUCCESS; /* key or tree is locked, just skip it */
8937  } else if (status != DB_SUCCESS) {
8938  cm_msg(MERROR, "db_paste_node", "cannot load array element \"%s\": db_set_data_index() status %d", mxml_get_attribute(node, "name"), status);
8939  return status;
8940  }
8941  }
8942  }
8943 
8944  } else { /* single value */
8945  if (tid == TID_STRING || tid == TID_LINK) {
8946  size = atoi(mxml_get_attribute(node, "size"));
8947  if (mxml_get_value(node) == NULL) {
8948  status = db_set_data(hDB, hKey, "", size, 1, tid);
8949  if (status == DB_NO_ACCESS) {
8950  cm_msg(MINFO, "db_paste_node", "cannot load string or link \"%s\": write protected", mxml_get_attribute(node, "name"));
8951  return DB_SUCCESS; /* key or tree is locked, just skip it */
8952  } else if (status != DB_SUCCESS) {
8953  cm_msg(MERROR, "db_paste_node", "cannot load string or link \"%s\": db_set_data() status %d", mxml_get_attribute(node, "name"), status);
8954  return status;
8955  }
8956  } else {
8957  strlcpy(buf, mxml_get_value(node), size);
8958  status = db_set_data(hDB, hKey, buf, size, 1, tid);
8959  if (status == DB_NO_ACCESS) {
8960  cm_msg(MINFO, "db_paste_node", "cannot load value \"%s\": write protected", mxml_get_attribute(node, "name"));
8961  return DB_SUCCESS; /* key or tree is locked, just skip it */
8962  } else if (status != DB_SUCCESS) {
8963  cm_msg(MERROR, "db_paste_node", "cannot load value \"%s\": db_set_data() status %d", mxml_get_attribute(node, "name"), status);
8964  return status;
8965  }
8966  }
8967  } else {
8968  char data[256];
8969  db_sscanf(mxml_get_value(node), data, &size, 0, tid);
8970  status = db_set_data(hDB, hKey, data, rpc_tid_size(tid), 1, tid);
8971  if (status == DB_NO_ACCESS) {
8972  cm_msg(MINFO, "db_paste_node", "cannot load value \"%s\": write protected", mxml_get_attribute(node, "name"));
8973  return DB_SUCCESS; /* key or tree is locked, just skip it */
8974  } else if (status != DB_SUCCESS) {
8975  cm_msg(MERROR, "db_paste_node", "cannot load value \"%s\": db_set_data() status %d", mxml_get_attribute(node, "name"), status);
8976  return status;
8977  }
8978  }
8979  }
8980 
8981  if (buf) {
8982  free(buf);
8983  buf = NULL;
8984  }
8985  }
8986 
8987  return DB_SUCCESS;
8988 }
static int db_paste_node(HNDLE hDB, HNDLE hKeyRoot, PMXML_NODE node)
Definition: odb.cxx:8780
INT db_set_num_values(HNDLE hDB, HNDLE hKey, INT num_values)
Definition: odb.cxx:7496
int rpc_name_tid(const char *name)
Definition: midas.cxx:11745
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_paste_xml()

INT EXPRT db_paste_xml ( HNDLE  hDB,
HNDLE  hKeyRoot,
const char *  buffer 
)

Paste an ODB subtree in XML format from a buffer

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyRootHandle for key where search starts, zero for root.
bufferNULL-terminated buffer
Returns
DB_SUCCESS, DB_INVALID_PARAM, DB_NO_MEMORY, DB_TYPE_MISMATCH

Definition at line 8998 of file odb.cxx.

8999 {
9000  char error[256];
9001  INT status;
9002  PMXML_NODE tree, node;
9003 
9004  if (hKeyRoot == 0)
9005  db_find_key(hDB, hKeyRoot, "", &hKeyRoot);
9006 
9007  /* parse XML buffer */
9008  tree = mxml_parse_buffer(buffer, error, sizeof(error), NULL);
9009  if (tree == NULL) {
9010  puts(error);
9011  return DB_TYPE_MISMATCH;
9012  }
9013 
9014  node = mxml_find_node(tree, "odb");
9015  if (node == NULL) {
9016  puts("Cannot find element \"odb\" in XML data");
9017  return DB_TYPE_MISMATCH;
9018  }
9019 
9020  status = db_paste_node(hDB, hKeyRoot, node);
9021 
9022  mxml_free_tree(tree);
9023 
9024  return status;
9025 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_pkey_to_hkey()

static HNDLE db_pkey_to_hkey ( const DATABASE_HEADER pheader,
const KEY pkey 
)
static

Definition at line 1028 of file odb.cxx.

1029 {
1030  return (POINTER_T) pkey - (POINTER_T) pheader;
1031 }
Here is the caller graph for this function:

◆ db_print_msg()

void db_print_msg ( const db_err_msg msg)
static

Definition at line 116 of file odb.cxx.

117 {
118  while (msg != NULL) {
119  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());
120  msg = msg->next;
121  }
122 }
Here is the caller graph for this function:

◆ db_protect_database()

INT EXPRT db_protect_database ( HNDLE  hDB)

Protect a database for read/write access outside of the db_xxx functions

Parameters
hDBODB handle obtained via cm_get_experiment_database().
Returns
DB_SUCCESS, DB_INVALID_HANDLE

Definition at line 3157 of file odb.cxx.

3158 {
3159  if (rpc_is_remote())
3160  return DB_SUCCESS;
3161 
3162 #ifdef LOCAL_ROUTINES
3163  if (hDB > _database_entries || hDB <= 0) {
3164  cm_msg(MERROR, "db_protect_database", "invalid database handle %d", hDB);
3165  return DB_INVALID_HANDLE;
3166  }
3167 
3168  _database[hDB - 1].protect = TRUE;
3169  ss_shm_protect(_database[hDB - 1].shm_handle, _database[hDB - 1].database_header, _database[hDB - 1].shm_size);
3170  _database[hDB - 1].database_header = NULL;
3171 #endif /* LOCAL_ROUTINES */
3172  return DB_SUCCESS;
3173 }
INT ss_shm_protect(HNDLE handle, void *adr, size_t shm_size)
Definition: system.cxx:1009
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_recurse_record_tree_locked() [1/2]

static void db_recurse_record_tree_locked ( HNDLE  hDB,
const DATABASE_HEADER pheader,
const KEY pkey,
void **  data,
INT total_size,
INT  base_align,
INT max_align,
BOOL  bSet,
INT  convert_flags,
db_err_msg **  msg 
)
static

Definition at line 11443 of file odb.cxx.

11452 {
11453  const KEY *pold;
11454  INT size, align, corr, total_size_tmp;
11455 
11456  KEYLIST *pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
11457  if (!pkeylist->first_key)
11458  return;
11459  // FIXME: validate pkeylist->first_key
11460  pkey = (const KEY *) ((char *) pheader + pkeylist->first_key);
11461 
11462  /* first browse through this level */
11463  do {
11464  pold = NULL;
11465 
11466  if (pkey->type == TID_LINK) {
11467  const KEY *plink = db_resolve_link_locked(pheader, pkey, NULL, msg);
11468 
11469  if (!plink)
11470  return;
11471 
11472  if (plink->type == TID_KEY) {
11473  db_recurse_record_tree_locked(hDB, pheader, plink, data, total_size, base_align, NULL, bSet, convert_flags, msg);
11474  } else {
11475  pold = pkey;
11476  pkey = plink;
11477  }
11478  }
11479 
11480  if (pkey->type != TID_KEY) {
11481  /* correct for alignment */
11482  align = 1;
11483 
11484  if (rpc_tid_size(pkey->type))
11485  align = rpc_tid_size(pkey->type) < base_align ? rpc_tid_size(pkey->type) : base_align;
11486 
11487  if (max_align && align > *max_align)
11488  *max_align = align;
11489 
11490  corr = VALIGN(*total_size, align) - *total_size;
11491  *total_size += corr;
11492  if (data)
11493  *data = (void *) ((char *) (*data) + corr);
11494 
11495  /* calculate data size */
11496  size = pkey->item_size * pkey->num_values;
11497 
11498  if (data) {
11499  if (bSet) {
11500  KEY* wpkey = (KEY*)pkey;
11501  /* copy data if there is write access */
11502  if (pkey->access_mode & MODE_WRITE) {
11503  memcpy((char *) pheader + pkey->data, *data, pkey->item_size * pkey->num_values);
11504 
11505  /* convert data */
11506  if (convert_flags) {
11507  if (pkey->num_values > 1)
11508  rpc_convert_data((char *) pheader + pkey->data,
11509  pkey->type, RPC_FIXARRAY, pkey->item_size * pkey->num_values, convert_flags);
11510  else
11511  rpc_convert_single((char *) pheader + pkey->data, pkey->type, 0, convert_flags);
11512  }
11513 
11514  /* update time */
11515  wpkey->last_written = ss_time();
11516 
11517  /* notify clients which have key open */
11518  db_notify_clients_locked(pheader, hDB, db_pkey_to_hkey(pheader, pkey), -1, TRUE, msg);
11519  }
11520  } else {
11521  /* copy key data if there is read access */
11522  if (pkey->access_mode & MODE_READ) {
11523  memcpy(*data, (char *) pheader + pkey->data, pkey->item_size * pkey->num_values);
11524 
11525  /* convert data */
11526  if (convert_flags) {
11527  if (pkey->num_values > 1)
11528  rpc_convert_data(*data, pkey->type,
11530  pkey->item_size * pkey->num_values, convert_flags);
11531  else
11532  rpc_convert_single(*data, pkey->type, RPC_OUTGOING, convert_flags);
11533  }
11534  }
11535  }
11536 
11537  *data = (char *) (*data) + size;
11538  }
11539 
11540  *total_size += size;
11541  } else {
11542  /* align new substructure according to the maximum
11543  align value in this structure */
11544  align = 1;
11545 
11546  total_size_tmp = *total_size;
11547  db_recurse_record_tree_locked(hDB, pheader, pkey, NULL, &total_size_tmp, base_align, &align, bSet, convert_flags, msg);
11548 
11549  if (max_align && align > *max_align)
11550  *max_align = align;
11551 
11552  corr = VALIGN(*total_size, align) - *total_size;
11553  *total_size += corr;
11554  if (data)
11555  *data = (void *) ((char *) (*data) + corr);
11556 
11557  /* now recurse subtree */
11558  db_recurse_record_tree_locked(hDB, pheader, pkey, data, total_size, base_align, NULL, bSet, convert_flags, msg);
11559 
11560  corr = VALIGN(*total_size, align) - *total_size;
11561  *total_size += corr;
11562  if (data)
11563  *data = (void *) ((char *) (*data) + corr);
11564  }
11565 
11566  if (pold) {
11567  pkey = pold;
11568  pold = NULL;
11569  }
11570 
11571  if (!pkey->next_key)
11572  break;
11573 
11574  // FIXME: validate pkey->next_key
11575  pkey = (KEY *) ((char *) pheader + pkey->next_key);
11576  } while (TRUE);
11577 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_recurse_record_tree_locked() [2/2]

static void db_recurse_record_tree_locked ( HNDLE  hDB,
HNDLE  hKey,
void **  data,
INT total_size,
INT  base_align,
INT max_align,
BOOL  bSet,
INT  convert_flags,
db_err_msg **  msg 
)
static

Definition at line 11579 of file odb.cxx.

11588 {
11589  /* get first subkey of hKey */
11590  DATABASE_HEADER *pheader = _database[hDB - 1].database_header;
11591 
11592  const KEY* pkey = db_get_pkey(pheader, hKey, NULL, "db_recurse_record_tree", msg);
11593 
11594  if (!pkey) {
11595  return;
11596  }
11597 
11598  db_recurse_record_tree_locked(hDB, pheader, pkey, data, total_size, base_align, max_align, bSet, convert_flags, msg);
11599 }
Here is the call graph for this function:

◆ db_remove_open_record()

INT EXPRT db_remove_open_record ( HNDLE  hDB,
HNDLE  hKey,
BOOL  lock 
)

Definition at line 12502 of file odb.cxx.

12510 {
12511  if (rpc_is_remote())
12512  return rpc_call(RPC_DB_REMOVE_OPEN_RECORD, hDB, hKey, lock);
12513 
12514  int status = DB_SUCCESS;
12515 
12516 #ifdef LOCAL_ROUTINES
12517  {
12518  if (hDB > _database_entries || hDB <= 0) {
12519  cm_msg(MERROR, "db_remove_open_record", "invalid database handle %d", hDB);
12520  return DB_INVALID_HANDLE;
12521  }
12522 
12524 
12525  DATABASE *pdb = &_database[hDB - 1];
12526  DATABASE_HEADER *pheader = pdb->database_header;
12527 
12528  db_allow_write_locked(pdb, "db_remove_open_record");
12529 
12530  status = db_remove_open_record_wlocked(pdb, pheader, hKey);
12531 
12533  }
12534 #endif /* LOCAL_ROUTINES */
12535 
12536  return status;
12537 }
#define RPC_DB_REMOVE_OPEN_RECORD
Definition: mrpc.h:73
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_remove_open_record_wlocked()

static int db_remove_open_record_wlocked ( DATABASE pdb,
DATABASE_HEADER pheader,
HNDLE  hKey 
)
static

Definition at line 12456 of file odb.cxx.

12457 {
12458  int status = DB_SUCCESS;
12459 
12460  DATABASE_CLIENT *pclient = db_get_my_client_locked(pdb);
12461 
12462  /* search key */
12463  int idx;
12464  for (idx = 0; idx < pclient->max_index; idx++)
12465  if (pclient->open_record[idx].handle == hKey)
12466  break;
12467 
12468  if (idx == pclient->max_index) {
12469  return DB_INVALID_HANDLE;
12470  }
12471 
12472  KEY* pkey = (KEY*)db_get_pkey(pheader, hKey, &status, "db_remove_open_record_wlocked", NULL);
12473 
12474  if (!pkey)
12475  return status;
12476 
12477  /* decrement notify_count */
12478 
12479  if (pkey->notify_count > 0)
12480  pkey->notify_count--;
12481 
12482  pclient->num_open_records--;
12483 
12484  /* remove exclusive flag */
12485  if (pclient->open_record[idx].access_mode & MODE_WRITE)
12486  db_set_mode_wlocked(pheader, pkey, (WORD) (pkey->access_mode & ~MODE_EXCLUSIVE), 2, NULL);
12487 
12488  memset(&pclient->open_record[idx], 0, sizeof(OPEN_RECORD));
12489 
12490  /* calculate new max_index entry */
12491  int i;
12492  for (i = pclient->max_index - 1; i >= 0; i--)
12493  if (pclient->open_record[i].handle != 0)
12494  break;
12495  pclient->max_index = i + 1;
12496 
12497  return DB_SUCCESS;
12498 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_rename_key()

INT EXPRT db_rename_key ( HNDLE  hDB,
HNDLE  hKey,
const char *  name 
)

dox

Definition at line 6251 of file odb.cxx.

6272 {
6273  if (rpc_is_remote())
6274  return rpc_call(RPC_DB_RENAME_KEY, hDB, hKey, name);
6275 
6276 #ifdef LOCAL_ROUTINES
6277  {
6278  DATABASE_HEADER *pheader;
6279  KEY *pkey;
6280  int status;
6281 
6282  if (hDB > _database_entries || hDB <= 0) {
6283  cm_msg(MERROR, "db_rename_key", "invalid database handle");
6284  return DB_INVALID_HANDLE;
6285  }
6286 
6287  if (!_database[hDB - 1].attached) {
6288  cm_msg(MERROR, "db_rename_key", "invalid database handle");
6289  return DB_INVALID_HANDLE;
6290  }
6291 
6292  if (hKey < (int) sizeof(DATABASE_HEADER)) {
6293  cm_msg(MERROR, "db_rename_key", "invalid key handle");
6294  return DB_INVALID_HANDLE;
6295  }
6296 
6297  db_err_msg* msg = NULL;
6298  status = db_validate_name(name, FALSE, "db_rename_key", &msg);
6299  if (msg)
6300  db_flush_msg(&msg);
6301  if (status != DB_SUCCESS)
6302  return status;
6303 
6304  if (name == NULL) {
6305  cm_msg(MERROR, "db_rename_key", "key name is NULL");
6306  return DB_INVALID_NAME;
6307  }
6308 
6309  if (strlen(name) < 1) {
6310  cm_msg(MERROR, "db_rename_key", "key name is too short");
6311  return DB_INVALID_NAME;
6312  }
6313 
6314  if (strchr(name, '/')) {
6315  cm_msg(MERROR, "db_rename_key", "key name may not contain \"/\"");
6316  return DB_INVALID_NAME;
6317  }
6318 
6320 
6321  pheader = _database[hDB - 1].database_header;
6322 
6323  /* check if hKey argument is correct */
6324  if (!db_validate_hkey(pheader, hKey)) {
6326  return DB_INVALID_HANDLE;
6327  }
6328 
6329  pkey = (KEY *) ((char *) pheader + hKey);
6330 
6331  if (!pkey->type) {
6332  int pkey_type = pkey->type;
6334  cm_msg(MERROR, "db_rename_key", "hkey %d invalid key type %d", hKey, pkey_type);
6335  return DB_INVALID_HANDLE;
6336  }
6337 
6338  db_allow_write_locked(&_database[hDB - 1], "db_rename_key");
6339 
6340  strlcpy(pkey->name, name, NAME_LENGTH);
6341 
6343 
6344  }
6345 #endif /* LOCAL_ROUTINES */
6346 
6347  return DB_SUCCESS;
6348 }
#define RPC_DB_RENAME_KEY
Definition: mrpc.h:77
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_reorder_key()

INT EXPRT db_reorder_key ( HNDLE  hDB,
HNDLE  hKey,
INT  idx 
)

Definition at line 6351 of file odb.cxx.

6374 {
6375  if (rpc_is_remote())
6376  return rpc_call(RPC_DB_REORDER_KEY, hDB, hKey, idx);
6377 
6378 #ifdef LOCAL_ROUTINES
6379  {
6380  DATABASE_HEADER *pheader;
6381  KEY *pkey, *pnext_key, *pkey_tmp;
6382  KEYLIST *pkeylist;
6383  INT i;
6384 
6385  if (hDB > _database_entries || hDB <= 0) {
6386  cm_msg(MERROR, "db_rename_key", "invalid database handle");
6387  return DB_INVALID_HANDLE;
6388  }
6389 
6390  if (!_database[hDB - 1].attached) {
6391  cm_msg(MERROR, "db_rename_key", "invalid database handle");
6392  return DB_INVALID_HANDLE;
6393  }
6394 
6395  if (hKey < (int) sizeof(DATABASE_HEADER)) {
6396  cm_msg(MERROR, "db_rename_key", "invalid key handle");
6397  return DB_INVALID_HANDLE;
6398  }
6399 
6401 
6402  pheader = _database[hDB - 1].database_header;
6403 
6404  /* check if hKey argument is correct */
6405  if (!db_validate_hkey(pheader, hKey)) {
6407  return DB_INVALID_HANDLE;
6408  }
6409 
6410  pkey = (KEY *) ((char *) pheader + hKey);
6411 
6412  if (!pkey->type) {
6413  int pkey_type = pkey->type;
6415  cm_msg(MERROR, "db_reorder_key", "hkey %d invalid key type %d", hKey, pkey_type);
6416  return DB_INVALID_HANDLE;
6417  }
6418 
6419  if (!(pkey->access_mode & MODE_WRITE)) {
6421  return DB_NO_ACCESS;
6422  }
6423 
6424  /* check if someone has opened key or parent */
6425  do {
6426 #ifdef CHECK_OPEN_RECORD
6427  if (pkey->notify_count) {
6429  return DB_OPEN_RECORD;
6430  }
6431 #endif
6432  if (pkey->parent_keylist == 0)
6433  break;
6434 
6435  pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
6436  // FIXME: validate pkeylist->parent
6437  pkey = (KEY *) ((char *) pheader + pkeylist->parent);
6438  } while (TRUE);
6439 
6440  db_allow_write_locked(&_database[hDB - 1], "db_reorder_key");
6441 
6442  pkey = (KEY *) ((char *) pheader + hKey); // NB: hKey is already validated
6443  pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
6444 
6445  /* first remove key from list */
6446  pnext_key = (KEY *) (POINTER_T) pkey->next_key; // FIXME: what is this pointer cast?
6447 
6448  if ((KEY *) ((char *) pheader + pkeylist->first_key) == pkey) {
6449  /* key is first in list */
6450  pkeylist->first_key = (POINTER_T) pnext_key;
6451  } else {
6452  /* find predecessor */
6453  // FIXME: validate pkeylist->first_key
6454  pkey_tmp = (KEY *) ((char *) pheader + pkeylist->first_key);
6455  while ((KEY *) ((char *) pheader + pkey_tmp->next_key) != pkey) {
6456  // FIXME: validate pkey_tmp->next_key
6457  pkey_tmp = (KEY *) ((char *) pheader + pkey_tmp->next_key);
6458  }
6459  pkey_tmp->next_key = (POINTER_T) pnext_key;
6460  }
6461 
6462  /* add key to list at proper index */
6463  // FIXME: validate pkeylist->first_key
6464  pkey_tmp = (KEY *) ((char *) pheader + pkeylist->first_key);
6465  if (idx < 0 || idx >= pkeylist->num_keys - 1) {
6466  /* add at bottom */
6467 
6468  /* find last key */
6469  for (i = 0; i < pkeylist->num_keys - 2; i++) {
6470  // FIXME: validate pkey_tmp->next_key
6471  pkey_tmp = (KEY *) ((char *) pheader + pkey_tmp->next_key);
6472  }
6473 
6474  pkey_tmp->next_key = (POINTER_T) pkey - (POINTER_T) pheader;
6475  pkey->next_key = 0;
6476  } else {
6477  if (idx == 0) {
6478  /* add at top */
6479  pkey->next_key = pkeylist->first_key;
6480  pkeylist->first_key = (POINTER_T) pkey - (POINTER_T) pheader;
6481  } else {
6482  /* add at position index */
6483  for (i = 0; i < idx - 1; i++) {
6484  // FIXME: validate pkey_tmp->next_key
6485  pkey_tmp = (KEY *) ((char *) pheader + pkey_tmp->next_key);
6486  }
6487 
6488  pkey->next_key = pkey_tmp->next_key;
6489  pkey_tmp->next_key = (POINTER_T) pkey - (POINTER_T) pheader;
6490  }
6491  }
6492 
6494 
6495  }
6496 #endif /* LOCAL_ROUTINES */
6497 
6498  return DB_SUCCESS;
6499 }
#define RPC_DB_REORDER_KEY
Definition: mrpc.h:79
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_resize_string()

INT EXPRT db_resize_string ( HNDLE  hdb,
HNDLE  hKeyRoot,
const char *  key_name,
int  num_values,
int  max_string_length 
)

Change size of string arrays.

This function can change the number of elements and the string element length of an array of strings.

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
key_nameOdb key name, if NULL, will resize ODB entry pointed to by hKey
num_valuesNew number of array elements, if 0, remains unchanged
max_string_lengthNew max string length for array elements, if 0, remains unchanged
Returns
DB_SUCCESS, or error from db_find_key, db_create_key, db_get_data(), db_set_data()

Definition at line 14028 of file odb.cxx.

14029 {
14030  int status;
14031  int hkey;
14032 
14033  //printf("db_resize_string: key_name [%s], num_values %d, max_string_length %d\n", key_name, num_values, max_string_length);
14034 
14035  int old_num_values = 0;
14036  int old_item_size = 0;
14037  int old_size = 0;
14038  char* old_data = NULL;
14039 
14040  if (key_name) {
14041  status = db_find_key(hdb, hKeyRoot, key_name, &hkey);
14042  } else {
14043  hkey = hKeyRoot;
14044  status = DB_SUCCESS;
14045  }
14046  if (status == DB_SUCCESS) {
14047  KEY key;
14048  status = db_get_key(hdb, hkey, &key);
14049  if (status != DB_SUCCESS)
14050  return status;
14051  old_num_values = key.num_values;
14052  old_item_size = key.item_size;
14053  old_size = old_num_values * old_item_size;
14054  if (old_size > 0) {
14055  old_data = (char*)malloc(old_size);
14056  assert(old_data != NULL);
14057  int size = old_size;
14058  status = db_get_data(hdb, hkey, old_data, &size, TID_STRING);
14059  if (status != DB_SUCCESS) {
14060  free(old_data);
14061  return status;
14062  }
14063  assert(size == old_size);
14064  }
14065  } else {
14066  status = db_create_key(hdb, hKeyRoot, key_name, TID_STRING);
14067  if (status != DB_SUCCESS)
14068  return status;
14069  status = db_find_key(hdb, hKeyRoot, key_name, &hkey);
14070  if (status != DB_SUCCESS)
14071  return status;
14072  }
14073 
14074  //printf("old_num_values %d, old_item_size %d, old_size %d\n", old_num_values, old_item_size, old_size);
14075 
14076  int item_size = max_string_length;
14077 
14078  if (item_size < 1)
14079  item_size = old_item_size;
14080 
14081  if (num_values < 1)
14082  num_values = old_num_values;
14083 
14084  int new_size = num_values * item_size;
14085  char* new_data = (char*)malloc(new_size);
14086  assert(new_data);
14087 
14088  memset(new_data, 0, new_size);
14089 
14090  if (old_data) {
14091  int num = old_num_values;
14092  if (num > num_values)
14093  num = num_values;
14094 
14095  //printf("new num_values %d, item_size %d, new_size %d, old_size %d, to copy %d values\n", num_values, item_size, new_size, old_size, num);
14096 
14097  for (int i=0; i<num; i++) {
14098  const char* old_ptr = old_data + i*old_item_size;
14099  char* new_ptr = new_data + i*item_size;
14100  strlcpy(new_ptr, old_ptr, item_size);
14101  }
14102  }
14103 
14104  status = db_set_data(hdb, hkey, new_data, new_size, num_values, TID_STRING);
14105 
14106  if (old_data)
14107  free(old_data);
14108  if (new_data)
14109  free(new_data);
14110 
14111  return status;
14112 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_resolve_link_locked()

static const KEY * db_resolve_link_locked ( const DATABASE_HEADER pheader,
const KEY pkey,
int *  pstatus,
db_err_msg **  msg 
)
static

Definition at line 1097 of file odb.cxx.

1098 {
1099  if (pkey->type != TID_LINK)
1100  return pkey;
1101 
1102  // FIXME: need to validate pkey->data
1103 
1104  if (*((char *) pheader + pkey->data) == '/') {
1105  return db_find_pkey_locked(pheader, NULL, (char*)pheader + pkey->data, pstatus, msg);
1106  } else {
1107  return db_find_pkey_locked(pheader, pkey, (char*)pheader + pkey->data, pstatus, msg);
1108  }
1109 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_save()

INT EXPRT db_save ( HNDLE  hDB,
HNDLE  hKey,
const char *  filename,
BOOL  bRemote 
)

dox Save a branch of a database to an .ODB file

This function is used by the ODBEdit command save. For a description of the ASCII format, see db_copy(). Data of the whole ODB can be saved (hkey equal zero) or only a sub-tree.

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
filenameFilename of .ODB file.
bRemoteFlag for saving database on remote server.
Returns
DB_SUCCESS, DB_FILE_ERROR

Definition at line 9246 of file odb.cxx.

9247 {
9248  if (rpc_is_remote() && bRemote)
9249  return rpc_call(RPC_DB_SAVE, hDB, hKey, filename, bRemote);
9250 
9251 #ifdef LOCAL_ROUTINES
9252  {
9253  INT hfile, size, buffer_size, n, status;
9254  char *buffer, path[256];
9255 
9256  /* open file */
9257  hfile = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, 0644);
9258  if (hfile == -1) {
9259  cm_msg(MERROR, "db_save", "Cannot open file \"%s\"", filename);
9260  return DB_FILE_ERROR;
9261  }
9262 
9263  db_get_path(hDB, hKey, path, sizeof(path));
9264 
9265  buffer_size = 10000;
9266  do {
9267  buffer = (char *) malloc(buffer_size);
9268  if (buffer == NULL) {
9269  cm_msg(MERROR, "db_save", "cannot allocate ODB dump buffer");
9270  break;
9271  }
9272 
9273  size = buffer_size;
9274  status = db_copy(hDB, hKey, buffer, &size, path);
9275  if (status != DB_TRUNCATED) {
9276  n = write(hfile, buffer, buffer_size - size);
9277  free(buffer);
9278  buffer = NULL;
9279 
9280  if (n != buffer_size - size) {
9281  cm_msg(MERROR, "db_save", "cannot save .ODB file");
9282  close(hfile);
9283  return DB_FILE_ERROR;
9284  }
9285  break;
9286  }
9287 
9288  /* increase buffer size if truncated */
9289  free(buffer);
9290  buffer = NULL;
9291  buffer_size *= 2;
9292  } while (1);
9293 
9294  close(hfile);
9295 
9296  }
9297 #endif /* LOCAL_ROUTINES */
9298 
9299  return DB_SUCCESS;
9300 }
#define RPC_DB_SAVE
Definition: mrpc.h:74
#define write(n, a, f, d)
Definition: midas_macro.h:245
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_save_json()

INT EXPRT db_save_json ( HNDLE  hDB,
HNDLE  hKey,
const char *  filename,
int  flags 
)

Save a branch of a database to an .json file

This function is used by the ODBEdit command save to write the contents of the ODB into a JSON file. Data of the whole ODB can be saved (hkey equal zero) or only a sub-tree.

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
filenameFilename of .json file.
Returns
DB_SUCCESS, DB_FILE_ERROR

Definition at line 10531 of file odb.cxx.

10532 {
10533  INT status;
10534 
10535  /* open file */
10536  FILE *fp = fopen(filename, "w");
10537  if (fp == NULL) {
10538  cm_msg(MERROR, "db_save_json", "Cannot open file \"%s\", fopen() errno %d (%s)", filename, errno, strerror(errno));
10539  return DB_FILE_ERROR;
10540  }
10541 
10542  bool unlock = false;
10543 
10544  if (!rpc_is_remote()) {
10546  if (status != DB_SUCCESS) {
10547  return status;
10548  }
10549  unlock = true;
10550  }
10551 
10552  std::string path = db_get_path(hDB, hKey);
10553 
10554  bool emptySubdir = false;
10555  HNDLE hSubKey;
10556  status = db_enum_link(hDB, hKey, 0, &hSubKey);
10557  if (status == DB_NO_MORE_SUBKEYS)
10558  emptySubdir = true;
10559 
10560  char* buffer = NULL;
10561  int buffer_size = 0;
10562  int buffer_end = 0;
10563 
10564  json_write(&buffer, &buffer_size, &buffer_end, 0, "{\n", 0);
10565 
10566  json_write(&buffer, &buffer_size, &buffer_end, 1, "/MIDAS version", 1);
10567  json_write(&buffer, &buffer_size, &buffer_end, 0, " : ", 0);
10568  json_write(&buffer, &buffer_size, &buffer_end, 0, MIDAS_VERSION, 1);
10569  json_write(&buffer, &buffer_size, &buffer_end, 0, ",\n", 0);
10570 
10571  json_write(&buffer, &buffer_size, &buffer_end, 1, "/MIDAS git revision", 1);
10572  json_write(&buffer, &buffer_size, &buffer_end, 0, " : ", 0);
10573  json_write(&buffer, &buffer_size, &buffer_end, 0, GIT_REVISION, 1);
10574  json_write(&buffer, &buffer_size, &buffer_end, 0, ",\n", 0);
10575 
10576  json_write(&buffer, &buffer_size, &buffer_end, 1, "/filename", 1);
10577  json_write(&buffer, &buffer_size, &buffer_end, 0, " : ", 0);
10578  json_write(&buffer, &buffer_size, &buffer_end, 0, filename, 1);
10579  json_write(&buffer, &buffer_size, &buffer_end, 0, ",\n", 0);
10580 
10581  json_write(&buffer, &buffer_size, &buffer_end, 1, "/ODB path", 1);
10582  json_write(&buffer, &buffer_size, &buffer_end, 0, " : ", 0);
10583  json_write(&buffer, &buffer_size, &buffer_end, 0, path.c_str(), 1);
10584 
10585  if (emptySubdir)
10586  json_write(&buffer, &buffer_size, &buffer_end, 0, "", 0);
10587  else
10588  json_write(&buffer, &buffer_size, &buffer_end, 0, ",\n", 0);
10589 
10590  //status = db_save_json_key_obsolete(hDB, hKey, -1, &buffer, &buffer_size, &buffer_end, 1, 0, 1);
10591  status = json_write_bare_subdir(hDB, hKey, &buffer, &buffer_size, &buffer_end, JS_LEVEL_1, flags, 0);
10592 
10593  json_write(&buffer, &buffer_size, &buffer_end, 0, "\n}\n", 0);
10594 
10595  if (unlock) {
10597  }
10598 
10599  if (status == DB_SUCCESS) {
10600  if (buffer) {
10601  size_t wr = fwrite(buffer, 1, buffer_end, fp);
10602  if (wr != (size_t)buffer_end) {
10603  cm_msg(MERROR, "db_save_json", "Cannot write to file \"%s\", fwrite() errno %d (%s)", filename, errno, strerror(errno));
10604  free(buffer);
10605  fclose(fp);
10606  return DB_FILE_ERROR;
10607  }
10608  }
10609  }
10610 
10611  if (buffer)
10612  free(buffer);
10613 
10614  fclose(fp);
10615 
10616  return DB_SUCCESS;
10617 }
int json_write_bare_subdir(HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end, int level, int flags, time_t timestamp)
Definition: odb.cxx:10356
#define MIDAS_VERSION
Definition: midas.h:37
#define JS_LEVEL_1
Definition: midas.h:1718
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_save_json_key_obsolete()

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 
)
static

Definition at line 9812 of file odb.cxx.

9813 {
9814  INT i, size, status;
9815  char *data;
9816  KEY key;
9817  KEY link_key;
9818  char link_path[MAX_ODB_PATH];
9819  int omit_top_level_braces = 0;
9820 
9821  //printf("db_save_json_key: key %d, level %d, save_keys %d, follow_links %d, recurse %d\n", hKey, level, save_keys, follow_links, recurse);
9822 
9823  if (level < 0) {
9824  level = 0;
9825  omit_top_level_braces = 1;
9826  }
9827 
9828  status = db_get_link(hDB, hKey, &key);
9829 
9830  if (status != DB_SUCCESS)
9831  return status;
9832 
9833  link_key = key;
9834 
9835  if (key.type == TID_LINK) {
9836  size = sizeof(link_path);
9837  status = db_get_data(hDB, hKey, link_path, &size, TID_LINK);
9838 
9839  if (status != DB_SUCCESS)
9840  return status;
9841 
9842  if (follow_links) {
9843  status = db_find_key(hDB, 0, link_path, &hKey);
9844 
9845  if (status != DB_SUCCESS)
9846  return status;
9847 
9848  status = db_get_key(hDB, hKey, &key);
9849 
9850  if (status != DB_SUCCESS)
9851  return status;
9852  }
9853  }
9854 
9855  //printf("key [%s] link [%s], type %d, link %d\n", key.name, link_key.name, key.type, link_key.type);
9856 
9857  if (key.type == TID_KEY && (recurse || level<=0)) {
9858  int idx = 0;
9859  int do_close_curly_bracket = 0;
9860 
9861  if (level == 0 && !omit_top_level_braces) {
9862  json_write(buffer, buffer_size, buffer_end, 0, "{\n", 0);
9863  do_close_curly_bracket = 1;
9864  }
9865  else if (level > 0) {
9866  json_write(buffer, buffer_size, buffer_end, level, link_key.name, 1);
9867  json_write(buffer, buffer_size, buffer_end, 0, " : {\n", 0);
9868  do_close_curly_bracket = 1;
9869  }
9870 
9871  if (level > 100) {
9872  char path[MAX_ODB_PATH];
9873  status = db_get_path(hDB, hKey, path, sizeof(path));
9874  if (status != DB_SUCCESS)
9875  strlcpy(path, "(path unknown)", sizeof(path));
9876 
9877  json_write(buffer, buffer_size, buffer_end, 0, "/error", 1);
9878  json_write(buffer, buffer_size, buffer_end, 0, " : ", 0);
9879  json_write(buffer, buffer_size, buffer_end, 0, "max nesting level exceed", 1);
9880 
9881  cm_msg(MERROR, "db_save_json_key", "max nesting level exceeded at \"%s\", check for symlink loops in this subtree", path);
9882 
9883  } else {
9884  HNDLE hSubkey;
9885 
9886  for (;; idx++) {
9887  db_enum_link(hDB, hKey, idx, &hSubkey);
9888 
9889  if (!hSubkey)
9890  break;
9891 
9892  if (idx != 0) {
9893  json_write(buffer, buffer_size, buffer_end, 0, ",\n", 0);
9894  }
9895 
9896  /* save subtree */
9897  status = db_save_json_key_obsolete(hDB, hSubkey, level + 1, buffer, buffer_size, buffer_end, save_keys, follow_links, recurse);
9898  if (status != DB_SUCCESS)
9899  return status;
9900  }
9901  }
9902 
9903  if (do_close_curly_bracket) {
9904  if (idx > 0)
9905  json_write(buffer, buffer_size, buffer_end, 0, "\n", 0);
9906  json_write(buffer, buffer_size, buffer_end, level, "}", 0);
9907  }
9908 
9909  } else {
9910 
9911  if (save_keys && level == 0) {
9912  json_write(buffer, buffer_size, buffer_end, 0, "{\n", 0);
9913  }
9914 
9915  /* save key value */
9916 
9917  if (save_keys == 1) {
9918  char str[NAME_LENGTH+15];
9919  sprintf(str, "%s/key", link_key.name);
9920 
9921  json_write(buffer, buffer_size, buffer_end, level, str, 1);
9922  json_write(buffer, buffer_size, buffer_end, 0, " : { ", 0);
9923 
9924  sprintf(str, "\"type\" : %d", key.type);
9925  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9926 
9927  if (link_key.type == TID_LINK && follow_links) {
9928  json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9929  json_write(buffer, buffer_size, buffer_end, 0, "link", 1);
9930  json_write(buffer, buffer_size, buffer_end, 0, ": ", 0);
9931  json_write(buffer, buffer_size, buffer_end, 0, link_path, 1);
9932  }
9933 
9934  if (key.num_values > 1) {
9935  json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9936 
9937  sprintf(str, "\"num_values\" : %d", key.num_values);
9938  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9939  }
9940 
9941  if (key.type == TID_STRING || key.type == TID_LINK) {
9942  json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9943 
9944  sprintf(str, "\"item_size\" : %d", key.item_size);
9945  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9946  }
9947 
9948  if (key.notify_count > 0) {
9949  json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9950 
9951  sprintf(str, "\"notify_count\" : %d", key.notify_count);
9952  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9953  }
9954 
9955  json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9956 
9957  sprintf(str, "\"access_mode\" : %d", key.access_mode);
9958  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9959 
9960  json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9961 
9962  sprintf(str, "\"last_written\" : %d", key.last_written);
9963  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9964 
9965  json_write(buffer, buffer_size, buffer_end, 0, " ", 0);
9966 
9967  json_write(buffer, buffer_size, buffer_end, 0, "}", 0);
9968 
9969  json_write(buffer, buffer_size, buffer_end, 0, ",\n", 0);
9970  }
9971 
9972  if (save_keys == 2) {
9973  char str[NAME_LENGTH+15];
9974  sprintf(str, "%s/last_written", link_key.name);
9975 
9976  json_write(buffer, buffer_size, buffer_end, level, str, 1);
9977 
9978  sprintf(str, " : %d", key.last_written);
9979  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9980 
9981  json_write(buffer, buffer_size, buffer_end, 0, ",\n", 0);
9982  }
9983 
9984  if (save_keys) {
9985  json_write(buffer, buffer_size, buffer_end, level, link_key.name, 1);
9986  json_write(buffer, buffer_size, buffer_end, 0, " : ", 0);
9987  }
9988 
9989  if (key.num_values > 1) {
9990  json_write(buffer, buffer_size, buffer_end, 0, "[ ", 0);
9991  }
9992 
9993  size = key.total_size;
9994  data = (char *) malloc(size);
9995  if (data == NULL) {
9996  cm_msg(MERROR, "db_save_json_key", "cannot allocate data buffer for %d bytes", size);
9997  return DB_NO_MEMORY;
9998  }
9999 
10000  if (key.type != TID_KEY) {
10001  if (follow_links)
10002  status = db_get_data(hDB, hKey, data, &size, key.type);
10003  else
10004  status = db_get_link_data(hDB, hKey, data, &size, key.type);
10005 
10006  if (status != DB_SUCCESS)
10007  return status;
10008  }
10009 
10010  for (i = 0; i < key.num_values; i++) {
10011  char str[256];
10012  char *p = data + key.item_size*i;
10013 
10014  if (i != 0)
10015  json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
10016 
10017  switch (key.type) {
10018  case TID_UINT8:
10019  sprintf(str, "%u", *(unsigned char*)p);
10020  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
10021  break;
10022  case TID_INT8:
10023  sprintf(str, "%d", *(char*)p);
10024  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
10025  break;
10026  case TID_CHAR:
10027  sprintf(str, "%c", *(char*)p);
10028  json_write(buffer, buffer_size, buffer_end, 0, str, 1);
10029  break;
10030  case TID_UINT16:
10031  sprintf(str, "\"0x%04x\"", *(WORD*)p);
10032  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
10033  break;
10034  case TID_INT16:
10035  sprintf(str, "%d", *(short*)p);
10036  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
10037  break;
10038  case TID_UINT32:
10039  sprintf(str, "\"0x%08x\"", *(DWORD*)p);
10040  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
10041  break;
10042  case TID_INT32:
10043  sprintf(str, "%d", *(int*)p);
10044  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
10045  break;
10046  case TID_UINT64:
10047  sprintf(str, "\"0x%08llx\"", *(UINT64*)p);
10048  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
10049  break;
10050  case TID_INT64:
10051  sprintf(str, "%lld", *(INT64*)p);
10052  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
10053  break;
10054  case TID_BOOL:
10055  if (*(int*)p)
10056  json_write(buffer, buffer_size, buffer_end, 0, "true", 0);
10057  else
10058  json_write(buffer, buffer_size, buffer_end, 0, "false", 0);
10059  break;
10060  case TID_FLOAT: {
10061  float flt = (*(float*)p);
10062  if (isnan(flt))
10063  json_write(buffer, buffer_size, buffer_end, 0, "\"NaN\"", 0);
10064  else if (isinf(flt)) {
10065  if (flt > 0)
10066  json_write(buffer, buffer_size, buffer_end, 0, "\"Infinity\"", 0);
10067  else
10068  json_write(buffer, buffer_size, buffer_end, 0, "\"-Infinity\"", 0);
10069  } else if (flt == 0)
10070  json_write(buffer, buffer_size, buffer_end, 0, "0", 0);
10071  else if (flt == (int)flt) {
10072  sprintf(str, "%.0f", flt);
10073  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
10074  } else {
10075  sprintf(str, "%.7e", flt);
10076  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
10077  }
10078  break;
10079  }
10080  case TID_DOUBLE: {
10081  double dbl = (*(double*)p);
10082  if (isnan(dbl))
10083  json_write(buffer, buffer_size, buffer_end, 0, "\"NaN\"", 0);
10084  else if (isinf(dbl)) {
10085  if (dbl > 0)
10086  json_write(buffer, buffer_size, buffer_end, 0, "\"Infinity\"", 0);
10087  else
10088  json_write(buffer, buffer_size, buffer_end, 0, "\"-Infinity\"", 0);
10089  } else if (dbl == 0)
10090  json_write(buffer, buffer_size, buffer_end, 0, "0", 0);
10091  else if (dbl == (int)dbl) {
10092  sprintf(str, "%.0f", dbl);
10093  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
10094  } else {
10095  sprintf(str, "%.16e", dbl);
10096  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
10097  }
10098  break;
10099  }
10100  case TID_BITFIELD:
10101  json_write(buffer, buffer_size, buffer_end, 0, "(TID_BITFIELD value)", 1);
10102  break;
10103  case TID_STRING:
10104  p[key.item_size-1] = 0; // make sure string is NUL terminated!
10105  json_write(buffer, buffer_size, buffer_end, 0, p, 1);
10106  break;
10107  case TID_ARRAY:
10108  json_write(buffer, buffer_size, buffer_end, 0, "(TID_ARRAY value)", 1);
10109  break;
10110  case TID_STRUCT:
10111  json_write(buffer, buffer_size, buffer_end, 0, "(TID_STRUCT value)", 1);
10112  break;
10113  case TID_KEY:
10114  json_write(buffer, buffer_size, buffer_end, 0, "{ }", 0);
10115  break;
10116  case TID_LINK:
10117  p[key.item_size-1] = 0; // make sure string is NUL terminated!
10118  json_write(buffer, buffer_size, buffer_end, 0, p, 1);
10119  break;
10120  default:
10121  json_write(buffer, buffer_size, buffer_end, 0, "(TID_UNKNOWN value)", 1);
10122  }
10123 
10124  }
10125 
10126  if (key.num_values > 1) {
10127  json_write(buffer, buffer_size, buffer_end, 0, " ]", 0);
10128  } else {
10129  json_write(buffer, buffer_size, buffer_end, 0, "", 0);
10130  }
10131 
10132  free(data);
10133  data = NULL;
10134 
10135  if (save_keys && level == 0) {
10136  json_write(buffer, buffer_size, buffer_end, 0, "\n}", 0);
10137  }
10138  }
10139 
10140  return DB_SUCCESS;
10141 }
#define TID_DOUBLE
Definition: midas.h:350
#define TID_BOOL
Definition: midas.h:347
#define TID_UINT64
Definition: midas.h:359
#define TID_INT64
Definition: midas.h:358
#define TID_STRUCT
Definition: midas.h:355
#define TID_UINT8
Definition: midas.h:335
#define TID_BITFIELD
Definition: midas.h:352
#define TID_INT8
Definition: midas.h:337
#define TID_ARRAY
Definition: midas.h:354
#define TID_CHAR
Definition: midas.h:338
#define TID_UINT16
Definition: midas.h:340
#define TID_INT16
Definition: midas.h:342
#define TID_FLOAT
Definition: midas.h:348
unsigned long long UINT64
Definition: midas.h:142
long long INT64
Definition: midas.h:143
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_save_string()

INT EXPRT db_save_string ( HNDLE  hDB,
HNDLE  hKey,
const char *  file_name,
const char *  string_name,
BOOL  append 
)

dox

Definition at line 10691 of file odb.cxx.

10714 {
10715  KEY key;
10716  char str[256], line[50+256];
10717  INT status, i, size, fh, buffer_size;
10718  char *buffer = NULL, *pc;
10719  int wr;
10720 
10721 
10722  /* open file */
10723  fh = open(file_name, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0644);
10724 
10725  if (fh == -1) {
10726  cm_msg(MERROR, "db_save_string", "Cannot open file\"%s\"", file_name);
10727  return DB_FILE_ERROR;
10728  }
10729 
10730  status = db_get_key(hDB, hKey, &key);
10731  if (status != DB_SUCCESS) {
10732  cm_msg(MERROR, "db_save_string", "cannot find key");
10733  return DB_INVALID_HANDLE;
10734  }
10735 
10736  if (string_name && string_name[0])
10737  strcpy(str, string_name);
10738  else
10739  strcpy(str, key.name);
10740 
10741  name2c(str);
10742  for (i = 0; i < (int) strlen(str); i++)
10743  str[i] = (char) toupper(str[i]);
10744 
10745  sprintf(line, "#define %s(_name) const char *_name[] = {\\\n", str);
10746  size = strlen(line);
10747  wr = write(fh, line, size);
10748  if (wr != size) {
10749  cm_msg(MERROR, "db_save", "file \"%s\" write error: write(%d) returned %d, errno %d (%s)", file_name, size, wr, errno, strerror(errno));
10750  close(fh);
10751  if (buffer)
10752  free(buffer);
10753  return DB_FILE_ERROR;
10754  }
10755 
10756  buffer_size = 10000;
10757  do {
10758  buffer = (char *) malloc(buffer_size);
10759  if (buffer == NULL) {
10760  cm_msg(MERROR, "db_save", "cannot allocate ODB dump buffer");
10761  break;
10762  }
10763 
10764  size = buffer_size;
10765  status = db_copy(hDB, hKey, buffer, &size, "");
10766  if (status != DB_TRUNCATED)
10767  break;
10768 
10769  /* increase buffer size if truncated */
10770  free(buffer);
10771  buffer = NULL;
10772  buffer_size *= 2;
10773  } while (1);
10774 
10775 
10776  pc = buffer;
10777 
10778  do {
10779  i = 0;
10780  line[i++] = '"';
10781  while (*pc != '\n' && *pc != 0) {
10782  if (*pc == '\"' || *pc == '\'')
10783  line[i++] = '\\';
10784  line[i++] = *pc++;
10785  }
10786  strcpy(&line[i], "\",\\\n");
10787  if (i > 0) {
10788  size = strlen(line);
10789  wr = write(fh, line, size);
10790  if (wr != size) {
10791  cm_msg(MERROR, "db_save", "file \"%s\" write error: write(%d) returned %d, errno %d (%s)", file_name, size, wr, errno, strerror(errno));
10792  close(fh);
10793  if (buffer)
10794  free(buffer);
10795  return DB_FILE_ERROR;
10796  }
10797  }
10798 
10799  if (*pc == '\n')
10800  pc++;
10801 
10802  } while (*pc);
10803 
10804  sprintf(line, "NULL }\n\n");
10805  size = strlen(line);
10806  wr = write(fh, line, size);
10807  if (wr != size) {
10808  cm_msg(MERROR, "db_save", "file \"%s\" write error: write(%d) returned %d, errno %d (%s)", file_name, size, wr, errno, strerror(errno));
10809  close(fh);
10810  if (buffer)
10811  free(buffer);
10812  return DB_FILE_ERROR;
10813  }
10814 
10815  close(fh);
10816  free(buffer);
10817 
10818  return DB_SUCCESS;
10819 }
void name2c(char *str)
Definition: odb.cxx:9098
char file_name[256]
Definition: odbhist.cxx:41
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_save_struct()

INT EXPRT db_save_struct ( HNDLE  hDB,
HNDLE  hKey,
const char *  file_name,
const char *  struct_name,
BOOL  append 
)

Save a branch of a database to a C structure .H file

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
file_nameFilename of .ODB file.
struct_nameName of structure. If struct_name == NULL, the name of the key is used.
appendIf TRUE, append to end of existing file
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_FILE_ERROR

Definition at line 10630 of file odb.cxx.

10631 {
10632  KEY key;
10633  char str[100], line[10+100];
10634  INT status, i, fh;
10635  int wr, size;
10636 
10637  /* open file */
10638  fh = open(file_name, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0644);
10639 
10640  if (fh == -1) {
10641  cm_msg(MERROR, "db_save_struct", "Cannot open file\"%s\"", file_name);
10642  return DB_FILE_ERROR;
10643  }
10644 
10645  status = db_get_key(hDB, hKey, &key);
10646  if (status != DB_SUCCESS) {
10647  cm_msg(MERROR, "db_save_struct", "cannot find key");
10648  return DB_INVALID_HANDLE;
10649  }
10650 
10651  sprintf(line, "typedef struct {\n");
10652 
10653  size = strlen(line);
10654  wr = write(fh, line, size);
10655  if (wr != size) {
10656  cm_msg(MERROR, "db_save_struct", "file \"%s\" write error: write(%d) returned %d, errno %d (%s)", file_name, size, wr, errno, strerror(errno));
10657  close(fh);
10658  return DB_FILE_ERROR;
10659  }
10660 
10661  db_save_tree_struct(hDB, hKey, fh, 0);
10662 
10663  if (struct_name && struct_name[0])
10664  strlcpy(str, struct_name, sizeof(str));
10665  else
10666  strlcpy(str, key.name, sizeof(str));
10667 
10668  name2c(str);
10669  for (i = 0; i < (int) strlen(str); i++)
10670  str[i] = (char) toupper(str[i]);
10671 
10672  sprintf(line, "} %s;\n\n", str);
10673 
10674  size = strlen(line);
10675  wr = write(fh, line, size);
10676  if (wr != size) {
10677  cm_msg(MERROR, "db_save_struct", "file \"%s\" write error: write(%d) returned %d, errno %d (%s)", file_name, size, wr, errno, strerror(errno));
10678  close(fh);
10679  return DB_FILE_ERROR;
10680  }
10681 
10682  close(fh);
10683 
10684  return DB_SUCCESS;
10685 }
static void db_save_tree_struct(HNDLE hDB, HNDLE hKey, int hfile, INT level)
Definition: odb.cxx:9119
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_save_tree_struct()

static void db_save_tree_struct ( HNDLE  hDB,
HNDLE  hKey,
int  hfile,
INT  level 
)
static

Definition at line 9119 of file odb.cxx.

9128 {
9129  INT i, idx;
9130  KEY key;
9131  HNDLE hSubkey;
9132  int wr;
9133 
9134  /* first enumerate this level */
9135  for (idx = 0;; idx++) {
9136  char name[MAX_ODB_PATH];
9137 
9138  db_enum_link(hDB, hKey, idx, &hSubkey);
9139  if (!hSubkey)
9140  break;
9141 
9142  /* first get the name of the link, than the type of the link target */
9143  db_get_key(hDB, hSubkey, &key);
9144  strlcpy(name, key.name, sizeof(name));
9145  db_enum_key(hDB, hKey, idx, &hSubkey);
9146 
9147  db_get_key(hDB, hSubkey, &key);
9148 
9149  if (key.type != TID_KEY) {
9150  char line[MAX_ODB_PATH];
9151  char str[MAX_ODB_PATH];
9152 
9153  for (i = 0; i <= level; i++) {
9154  wr = write(hfile, " ", 2);
9155  assert(wr == 2);
9156  }
9157 
9158  switch (key.type) {
9159  case TID_INT8:
9160  case TID_CHAR:
9161  strcpy(line, "char");
9162  break;
9163  case TID_INT16:
9164  strcpy(line, "short");
9165  break;
9166  case TID_FLOAT:
9167  strcpy(line, "float");
9168  break;
9169  case TID_DOUBLE:
9170  strcpy(line, "double");
9171  break;
9172  case TID_BITFIELD:
9173  strcpy(line, "unsigned char");
9174  break;
9175  case TID_STRING:
9176  strcpy(line, "char");
9177  break;
9178  case TID_LINK:
9179  strcpy(line, "char");
9180  break;
9181  default:
9182  strcpy(line, rpc_tid_name(key.type));
9183  break;
9184  }
9185 
9186  strlcat(line, " ", sizeof(line));
9187  strlcpy(str, name, sizeof(str));
9188  name2c(str);
9189 
9190  if (key.num_values > 1)
9191  sprintf(str + strlen(str), "[%d]", key.num_values);
9192  if (key.type == TID_STRING || key.type == TID_LINK)
9193  sprintf(str + strlen(str), "[%d]", key.item_size);
9194 
9195  strlcpy(line + 10, str, sizeof(line) - 10);
9196  strlcat(line, ";\n", sizeof(line));
9197 
9198  wr = write(hfile, line, strlen(line));
9199  assert(wr > 0);
9200  } else {
9201  char line[10+MAX_ODB_PATH];
9202  char str[MAX_ODB_PATH];
9203 
9204  /* recurse subtree */
9205  for (i = 0; i <= level; i++) {
9206  wr = write(hfile, " ", 2);
9207  assert(wr == 2);
9208  }
9209 
9210  sprintf(line, "struct {\n");
9211  wr = write(hfile, line, strlen(line));
9212  assert(wr > 0);
9213  db_save_tree_struct(hDB, hSubkey, hfile, level + 1);
9214 
9215  for (i = 0; i <= level; i++) {
9216  wr = write(hfile, " ", 2);
9217  assert(wr == 2);
9218  }
9219 
9220  strcpy(str, name);
9221  name2c(str);
9222 
9223  sprintf(line, "} %s;\n", str);
9224  wr = write(hfile, line, strlen(line));
9225  assert(wr > 0);
9226  }
9227  }
9228 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_save_xml()

INT EXPRT db_save_xml ( HNDLE  hDB,
HNDLE  hKey,
const char *  filename 
)

Save a branch of a database to an .xml file

This function is used by the ODBEdit command save to write the contents of the ODB into a XML file. Data of the whole ODB can be saved (hkey equal zero) or only a sub-tree.

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
filenameFilename of .XML file.
Returns
DB_SUCCESS, DB_FILE_ERROR

Definition at line 9483 of file odb.cxx.

9484 {
9485 #ifdef LOCAL_ROUTINES
9486  {
9487  INT status;
9488  char str[256];
9489  MXML_WRITER *writer;
9490 
9491  /* open file */
9492  writer = mxml_open_file(filename);
9493  if (writer == NULL) {
9494  cm_msg(MERROR, "db_save_xml", "Cannot open file \"%s\"", filename);
9495  return DB_FILE_ERROR;
9496  }
9497 
9498  db_get_path(hDB, hKey, str, sizeof(str));
9499 
9500  /* write XML header */
9501  mxml_start_element(writer, "odb");
9502  mxml_write_attribute(writer, "root", str);
9503  mxml_write_attribute(writer, "filename", filename);
9504  mxml_write_attribute(writer, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
9505 
9506  if (getenv("MIDASSYS"))
9507  strcpy(str, getenv("MIDASSYS"));
9508  else
9509  strcpy(str, "");
9510  strcat(str, DIR_SEPARATOR_STR);
9511  strcat(str, "odb.xsd");
9512  mxml_write_attribute(writer, "xsi:noNamespaceSchemaLocation", str);
9513 
9514  status = db_save_xml_key(hDB, hKey, 0, writer);
9515 
9516  mxml_end_element(writer); // "odb"
9517  mxml_close_file(writer);
9518 
9519  return status;
9520  }
9521 #endif /* LOCAL_ROUTINES */
9522 
9523  return DB_SUCCESS;
9524 }
#define DIR_SEPARATOR_STR
Definition: midas.h:194
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_save_xml_key()

INT db_save_xml_key ( HNDLE  hDB,
HNDLE  hKey,
INT  level,
MXML_WRITER *  writer 
)

Definition at line 9347 of file odb.cxx.

9348 {
9349  INT i, idx, size, status;
9350  char *data;
9351  HNDLE hSubkey;
9352  KEY key;
9353 
9354  status = db_get_link(hDB, hKey, &key);
9355  if (status != DB_SUCCESS)
9356  return status;
9357 
9358  if (key.type == TID_KEY) {
9359 
9360  /* save opening tag for subtree */
9361 
9362  if (level > 0) {
9363  mxml_start_element(writer, "dir");
9364  mxml_write_attribute(writer, "name", key.name);
9365  }
9366 
9367  for (idx = 0;; idx++) {
9368  db_enum_link(hDB, hKey, idx, &hSubkey);
9369 
9370  if (!hSubkey)
9371  break;
9372 
9373  /* save subtree */
9374  status = db_save_xml_key(hDB, hSubkey, level + 1, writer);
9375  if (status != DB_SUCCESS)
9376  return status;
9377  }
9378 
9379  /* save closing tag for subtree */
9380  if (level > 0)
9381  mxml_end_element(writer);
9382 
9383  } else {
9384  /* save key value */
9385 
9386  if (key.num_values > 1)
9387  mxml_start_element(writer, "keyarray");
9388  else
9389  mxml_start_element(writer, "key");
9390  mxml_write_attribute(writer, "name", key.name);
9391  mxml_write_attribute(writer, "type", rpc_tid_name(key.type));
9392 
9393  if (key.type == TID_STRING || key.type == TID_LINK) {
9394  char str[256];
9395  sprintf(str, "%d", key.item_size);
9396  mxml_write_attribute(writer, "size", str);
9397  }
9398 
9399  if (key.num_values > 1) {
9400  char str[256];
9401  sprintf(str, "%d", key.num_values);
9402  mxml_write_attribute(writer, "num_values", str);
9403  }
9404 
9405  size = key.total_size;
9406  data = (char *) malloc(size+1); // an extra byte to zero-terminate strings
9407  if (data == NULL) {
9408  cm_msg(MERROR, "db_save_xml_key", "cannot allocate data buffer");
9409  return DB_NO_MEMORY;
9410  }
9411 
9412  db_get_link_data(hDB, hKey, data, &size, key.type);
9413 
9414  if (key.num_values == 1) {
9415  if (key.type == TID_STRING) {
9416  data[size] = 0; // make sure strings are NUL-terminated
9417  mxml_write_value(writer, data);
9418  } else {
9419  char str[MAX_STRING_LENGTH];
9421  if (key.type == TID_STRING && strlen(data) >= MAX_STRING_LENGTH) {
9422  char path[MAX_ODB_PATH];
9423  db_get_path(hDB, hKey, path, sizeof(path));
9424  cm_msg(MERROR, "db_save_xml_key", "Long odb string probably truncated, odb path \"%s\", string length %d truncated to %d", path, (int)strlen(data), (int)strlen(str));
9425  }
9426  mxml_write_value(writer, str);
9427  }
9428  mxml_end_element(writer);
9429 
9430  } else { /* array of values */
9431 
9432  for (i = 0; i < key.num_values; i++) {
9433 
9434  mxml_start_element(writer, "value");
9435 
9436  {
9437  char str[256];
9438  sprintf(str, "%d", i);
9439  mxml_write_attribute(writer, "index", str);
9440  }
9441 
9442  if (key.type == TID_STRING) {
9443  char* p = data + i * key.item_size;
9444  p[key.item_size - 1] = 0; // make sure string is NUL-terminated
9445  //cm_msg(MINFO, "db_save_xml_key", "odb string array item_size %d, index %d length %d", key.item_size, i, (int)strlen(p));
9446  mxml_write_value(writer, p);
9447  } else {
9448  char str[MAX_STRING_LENGTH];
9450  if (key.type == TID_STRING && strlen(str) >= MAX_STRING_LENGTH-1) {
9451  char path[MAX_ODB_PATH];
9452  db_get_path(hDB, hKey, path, sizeof(path));
9453  cm_msg(MERROR, "db_save_xml_key", "Long odb string array probably truncated, odb path \"%s\"[%d]", path, i);
9454  }
9455  mxml_write_value(writer, str);
9456  }
9457 
9458  mxml_end_element(writer);
9459  }
9460 
9461  mxml_end_element(writer); /* keyarray */
9462  }
9463 
9464  free(data);
9465  data = NULL;
9466  }
9467 
9468  return DB_SUCCESS;
9469 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_scan_tree()

INT EXPRT db_scan_tree ( HNDLE  hDB,
HNDLE  hKey,
INT  level,
INT(*)(HNDLE, HNDLE, KEY *, INT, void *)  callback,
void *  info 
)

Definition at line 4757 of file odb.cxx.

4784 {
4785  HNDLE hSubkey;
4786  KEY key;
4787  INT i, status;
4788 
4789  status = db_get_link(hDB, hKey, &key);
4790  if (status != DB_SUCCESS)
4791  return status;
4792 
4793  status = callback(hDB, hKey, &key, level, info);
4794  if (status == 0)
4795  return status;
4796 
4797  if (key.type == TID_KEY) {
4798  for (i = 0;; i++) {
4799  db_enum_link(hDB, hKey, i, &hSubkey);
4800 
4801  if (!hSubkey)
4802  break;
4803 
4804  db_scan_tree(hDB, hSubkey, level + 1, callback, info);
4805  }
4806  }
4807 
4808  return DB_SUCCESS;
4809 }
struct callback_addr callback
Definition: mserver.cxx:25
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_scan_tree_link()

INT EXPRT db_scan_tree_link ( HNDLE  hDB,
HNDLE  hKey,
INT  level,
void(*)(HNDLE, HNDLE, KEY *, INT, void *)  callback,
void *  info 
)

Definition at line 4836 of file odb.cxx.

4864 {
4865  HNDLE hSubkey;
4866  KEY key;
4867  INT i, status;
4868 
4869  status = db_get_key(hDB, hKey, &key);
4870  if (status != DB_SUCCESS)
4871  return status;
4872 
4873  callback(hDB, hKey, &key, level, info);
4874 
4875  if (key.type == TID_KEY) {
4876  for (i = 0;; i++) {
4877  db_enum_link(hDB, hKey, i, &hSubkey);
4878 
4879  if (!hSubkey)
4880  break;
4881 
4882  db_scan_tree_link(hDB, hSubkey, level + 1, callback, info);
4883  }
4884  }
4885 
4886  return DB_SUCCESS;
4887 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_scan_tree_locked() [1/2]

static int db_scan_tree_locked ( const DATABASE_HEADER pheader,
const KEY pkey,
int  level,
int(*)(const DATABASE_HEADER *, const KEY *, int, void *, db_err_msg **)  callback,
void *  info,
db_err_msg **  msg 
)
static
Here is the caller graph for this function:

◆ db_scan_tree_locked() [2/2]

int db_scan_tree_locked ( const DATABASE_HEADER pheader,
const KEY pkey,
int  level,
int(*)(const DATABASE_HEADER *pheader, const KEY *, int, void *, db_err_msg **msg)  callback,
void *  info,
db_err_msg **  msg 
)

Definition at line 4813 of file odb.cxx.

4814 {
4815  assert(pkey != NULL);
4816  assert(level < MAX_ODB_PATH);
4817 
4818  int status = callback(pheader, pkey, level, info, msg);
4819  if (status == 0)
4820  return status;
4821 
4822  if (pkey->type == TID_KEY) {
4823  const KEY* subkey = db_enum_first_locked(pheader, pkey, msg);
4824  while (subkey != NULL) {
4825  db_scan_tree_locked(pheader, subkey, level + 1, callback, info, msg);
4826  subkey = db_enum_next_locked(pheader, pkey, subkey, msg);
4827  }
4828  }
4829 
4830  return DB_SUCCESS;
4831 }
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)
Here is the call graph for this function:

◆ db_scl()

MJsonNode *EXPRT db_scl ( HNDLE  hDB)

Definition at line 14114 of file odb.cxx.

14115 {
14116 #ifdef LOCAL_ROUTINES
14117  MJsonNode* scl = MJsonNode::MakeObject();
14118  MJsonNode* clients = MJsonNode::MakeArray();
14119 
14120  scl->AddToObject("now", MJsonNode::MakeNumber(ss_time_sec()));
14121  scl->AddToObject("clients", clients);
14122 
14123  /* lock database */
14125 
14126  DATABASE *pdb = &_database[hDB - 1];
14127  DATABASE_HEADER *pheader = pdb->database_header;
14128 
14129  DWORD now = ss_millitime();
14130 
14131  /* list clients */
14132  for (int i = 0; i < pheader->max_client_index; i++) {
14133  DATABASE_CLIENT *pclient = &pheader->client[i];
14134  if (pclient->pid) {
14135  MJsonNode* c = MJsonNode::MakeObject();
14136  c->AddToObject("slot", MJsonNode::MakeNumber(i));
14137  c->AddToObject("pid", MJsonNode::MakeNumber(pclient->pid));
14138  c->AddToObject("name", MJsonNode::MakeString(pclient->name));
14139  std::string path = msprintf("/System/Clients/%d/Host", pclient->pid);
14140  const KEY* pkey = db_find_pkey_locked(pheader, NULL, path.c_str(), NULL, NULL);
14141  if (pkey) {
14142  int host_size = pkey->total_size;
14143  char* host = (char*)malloc(host_size);
14144  assert(host != NULL);
14145  db_get_data_locked(pheader, pkey, 0, host, &host_size, TID_STRING, NULL);
14146  c->AddToObject("host", MJsonNode::MakeString(host));
14147  free(host);
14148  }
14149  c->AddToObject("watchdog_timeout_millisec", MJsonNode::MakeNumber(pclient->watchdog_timeout));
14150  // "now" and "last_activity" is millisecond time wrapped around at 32 bits, must do unsigned 32-bit math here, not in javascript
14151  c->AddToObject("last_activity_millisec", MJsonNode::MakeNumber(now - pclient->last_activity));
14152  clients->AddToArray(c);
14153  }
14154  }
14155 
14157 
14158  return scl;
14159 #else
14160  return MJsonNode::MakeNull();
14161 #endif
14162 }
double ss_time_sec()
Definition: system.cxx:3406
char c
Definition: system.cxx:1316
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_send_changed_records()

INT EXPRT db_send_changed_records ( )

Send all records to the ODB which were changed locally since the last call to this function.

This function is valid if used in conjunction with db_open_record() under the condition the record is open as MODE_WRITE access code.

//-------- BOF dbchange.c
typedef struct {
INT my_number;
float my_rate;
} MY_STATISTICS;
MY_STATISTICS myrec;
#define MY_STATISTICS(_name) char *_name[] = {\
"My Number = INT : 0",\
"My Rate = FLOAT : 0",\
"",\
NULL }
// Main
int main(unsigned int argc,char **argv)
{
INT lastnumber, status, msg;
char i, ch;
DWORD update_time, mainlast_time;
MY_STATISTICS (my_stat);
// set default
host_name[0] = 0;
expt_name[0] = 0;
// get default
// get parameters
for (i=1 ; i<argc ; i++)
{
if (argv[i][0] == '-' && argv[i][1] == 'd')
else if (argv[i][0] == '-')
{
if (i+1 >= argc || argv[i+1][0] == '-')
goto usage;
if (strncmp(argv[i],"-e",2) == 0)
strcpy(expt_name, argv[++i]);
else if (strncmp(argv[i],"-h",2)==0)
strcpy(host_name, argv[++i]);
}
else
{
printf("usage: dbchange [-h <Hostname>] [-e <Experiment>]\n");
return 0;
}
}
// connect to experiment
return 1;
// Connect to DB
// Create a default structure in ODB
db_create_record(hDB, 0, "My statistics", strcomb1(my_stat).c_str());
// Retrieve key for that strucutre in ODB
if (db_find_key(hDB, 0, "My statistics", &hKey) != DB_SUCCESS)
{
cm_msg(MERROR, "mychange", "cannot find My statistics");
goto error;
}
// Hot link this structure in Write mode
status = db_open_record(hDB, hKey, &myrec, sizeof(MY_STATISTICS), MODE_WRITE, NULL, NULL);
{
cm_msg(MERROR, "mychange", "cannot open My statistics record");
goto error;
}
// initialize ss_getchar()
// Main loop
do
{
// Update local structure
if ((ss_millitime() - update_time) > 100)
{
myrec.my_number += 1;
if (myrec.my_number - lastnumber) {
myrec.my_rate = 1000.f * (float) (myrec.my_number - lastnumber)
/ (float) (ss_millitime() - update_time);
}
update_time = ss_millitime();
lastnumber = myrec.my_number;
}
// Publish local structure to ODB (db_send_changed_record)
if ((ss_millitime() - mainlast_time) > 5000)
{
db_send_changed_records(); // <------- Call
mainlast_time = ss_millitime();
}
// Check for keyboard interaction
ch = 0;
while (ss_kbhit())
{
ch = ss_getchar(0);
if (ch == -1)
ch = getchar();
if ((char) ch == '!')
break;
}
msg = cm_yield(20);
} while (msg != RPC_SHUTDOWN && msg != SS_ABORT && ch != '!');
error:
return 1;
}
//-------- EOF dbchange.c
static void usage()
Definition: fetest_tmfe.cxx:98
INT cm_connect_experiment(const char *host_name, const char *exp_name, const char *client_name, void(*func)(char *))
Definition: midas.cxx:2280
INT cm_disconnect_experiment(void)
Definition: midas.cxx:2840
INT cm_get_environment(char *host_name, int host_name_size, char *exp_name, int exp_name_size)
Definition: midas.cxx:2136
#define CM_SUCCESS
Definition: midas.h:588
BOOL ss_kbhit()
Definition: system.cxx:3603
INT ss_getchar(BOOL reset)
Definition: system.cxx:7442
std::string strcomb1(const char **list)
Definition: odb.cxx:601
BOOL debug
debug printouts
Definition: mana.cxx:254
char host_name[HOST_NAME_LENGTH]
Definition: mana.cxx:242
char expt_name[NAME_LENGTH]
Definition: mevb.c:44
#define HOST_NAME_LENGTH
Definition: midas.h:280
Returns
DB_SUCCESS

Definition at line 13781 of file odb.cxx.

13782 {
13783  INT i;
13784 
13785  for (i = 0; i < _record_list_entries; i++)
13786  if (_record_list[i].access_mode & MODE_WRITE) {
13787  if (memcmp(_record_list[i].copy, _record_list[i].data, _record_list[i].buf_size) != 0) {
13788  if (rpc_is_remote()) {
13789  int align = ss_get_struct_align();
13791  } else {
13793  }
13794  memcpy(_record_list[i].copy, _record_list[i].data, _record_list[i].buf_size);
13795  }
13796  }
13797 
13798  return DB_SUCCESS;
13799 }
#define RPC_NO_REPLY
Definition: midas.h:403
#define RPC_DB_SET_RECORD
Definition: mrpc.h:71
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_client_name()

INT db_set_client_name ( HNDLE  hDB,
const char *  client_name 
)

Definition at line 2393 of file odb.cxx.

2412 {
2413  if (rpc_is_remote())
2414  return rpc_call(RPC_DB_SET_CLIENT_NAME, hDB, client_name);
2415 
2416 #ifdef LOCAL_ROUTINES
2417  {
2418  if (hDB > _database_entries || hDB <= 0) {
2419  cm_msg(MERROR, "db_set_client_name", "invalid database handle %d", hDB);
2420  return DB_INVALID_HANDLE;
2421  }
2422 
2424 
2425  DATABASE *pdb = &_database[hDB - 1];
2426  DATABASE_CLIENT *pclient = db_get_my_client_locked(pdb);
2427  strlcpy(pclient->name, client_name, sizeof(pclient->name));
2428 
2430  }
2431 #endif /* LOCAL_ROUTINES */
2432 
2433  return DB_SUCCESS;
2434 }
#define RPC_DB_SET_CLIENT_NAME
Definition: mrpc.h:76
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_data()

INT EXPRT db_set_data ( HNDLE  hDB,
HNDLE  hKey,
const void *  data,
INT  buf_size,
INT  num_values,
DWORD  type 
)

Set key data from a handle. Adjust number of values if previous data has different size.

HNLDE hkey;
// get key handle for run number
db_find_key(hDB, 0, "/Runinfo/Run number", &hkey);
// set run number
Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
dataBuffer from which data gets copied to.
buf_sizeSize of data buffer.
num_valuesNumber of data values (for arrays).
typeType of key, one of TID_xxx (see Midas_Data_Types).
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_TRUNCATED

Definition at line 7209 of file odb.cxx.

7210 {
7211  if (rpc_is_remote())
7212  return rpc_call(RPC_DB_SET_DATA, hDB, hKey, data, buf_size, num_values, type);
7213 
7214 #ifdef LOCAL_ROUTINES
7215  {
7216  DATABASE_HEADER *pheader;
7217  KEY *pkey;
7218  HNDLE hkeylink;
7219  int link_idx;
7220  char link_name[256];
7221  int status;
7222 
7223  if (hDB > _database_entries || hDB <= 0) {
7224  cm_msg(MERROR, "db_set_data", "invalid database handle");
7225  return DB_INVALID_HANDLE;
7226  }
7227 
7228  if (!_database[hDB - 1].attached) {
7229  cm_msg(MERROR, "db_set_data", "invalid database handle");
7230  return DB_INVALID_HANDLE;
7231  }
7232 
7233  if (hKey < (int) sizeof(DATABASE_HEADER)) {
7234  cm_msg(MERROR, "db_set_data", "invalid key handle");
7235  return DB_INVALID_HANDLE;
7236  }
7237 
7238  if (num_values == 0)
7239  return DB_INVALID_PARAM;
7240 
7242  db_err_msg* msg = NULL;
7243 
7244  pheader = _database[hDB - 1].database_header;
7245 
7246  /* check if hKey argument is correct */
7247  if (!db_validate_hkey(pheader, hKey)) {
7249  return DB_INVALID_HANDLE;
7250  }
7251 
7252  pkey = (KEY *) ((char *) pheader + hKey);
7253 
7254  /* check for write access */
7255  if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
7257  return DB_NO_ACCESS;
7258  }
7259 
7260  /* check for link to array index */
7261  if (pkey->type == TID_LINK) {
7262  strlcpy(link_name, (char *) pheader + pkey->data, sizeof(link_name));
7263  if (strlen(link_name) > 0 && link_name[strlen(link_name) - 1] == ']') {
7265  if (strchr(link_name, '[') == NULL)
7266  return DB_INVALID_LINK;
7267  link_idx = atoi(strchr(link_name, '[') + 1);
7268  *strchr(link_name, '[') = 0;
7269  if (db_find_key(hDB, 0, link_name, &hkeylink) != DB_SUCCESS)
7270  return DB_INVALID_LINK;
7271  return db_set_data_index(hDB, hkeylink, data, buf_size, link_idx, type);
7272  }
7273  }
7274 
7275  status = db_check_set_data_locked(pheader, pkey, data, buf_size, num_values, type, "db_set_data", &msg);
7276 
7277  if (status != DB_SUCCESS) {
7279  if (msg)
7280  db_flush_msg(&msg);
7281  return status;
7282  }
7283 
7284  db_allow_write_locked(&_database[hDB-1], "db_set_data");
7285 
7286  status = db_set_data_wlocked(pheader, pkey, data, buf_size, num_values, type, "db_set_data", &msg);
7287 
7288  if (status != DB_SUCCESS) {
7290  if (msg)
7291  db_flush_msg(&msg);
7292  return status;
7293  }
7294 
7295  db_notify_clients_locked(pheader, hDB, hKey, -1, TRUE, &msg);
7297  if (msg)
7298  db_flush_msg(&msg);
7299 
7300 
7301  }
7302 #endif /* LOCAL_ROUTINES */
7303 
7304  return DB_SUCCESS;
7305 }
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)
Definition: odb.cxx:7095
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)
Definition: odb.cxx:7008
#define RPC_DB_SET_DATA
Definition: mrpc.h:66
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_data1()

INT EXPRT db_set_data1 ( HNDLE  hDB,
HNDLE  hKey,
const void *  data,
INT  buf_size,
INT  num_values,
DWORD  type 
)

Definition at line 7307 of file odb.cxx.

7313 {
7314  if (rpc_is_remote())
7315  return rpc_call(RPC_DB_SET_DATA1, hDB, hKey, data, buf_size, num_values, type);
7316 
7317 #ifdef LOCAL_ROUTINES
7318  {
7319  DATABASE_HEADER *pheader;
7320  KEY *pkey;
7321  HNDLE hkeylink;
7322  int link_idx;
7323  char link_name[256];
7324  int status;
7325 
7326  if (hDB > _database_entries || hDB <= 0) {
7327  cm_msg(MERROR, "db_set_data1", "invalid database handle");
7328  return DB_INVALID_HANDLE;
7329  }
7330 
7331  if (!_database[hDB - 1].attached) {
7332  cm_msg(MERROR, "db_set_data1", "invalid database handle");
7333  return DB_INVALID_HANDLE;
7334  }
7335 
7336  if (hKey < (int) sizeof(DATABASE_HEADER)) {
7337  cm_msg(MERROR, "db_set_data1", "invalid key handle");
7338  return DB_INVALID_HANDLE;
7339  }
7340 
7341  if (num_values == 0)
7342  return DB_INVALID_PARAM;
7343 
7345  db_err_msg* msg = NULL;
7346 
7347  pheader = _database[hDB - 1].database_header;
7348 
7349  /* check if hKey argument is correct */
7350  if (!db_validate_hkey(pheader, hKey)) {
7352  return DB_INVALID_HANDLE;
7353  }
7354 
7355  pkey = (KEY *) ((char *) pheader + hKey);
7356 
7357  /* check for write access */
7358  if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
7360  return DB_NO_ACCESS;
7361  }
7362 
7363  /* check for link to array index */
7364  if (pkey->type == TID_LINK) {
7365  strlcpy(link_name, (char *) pheader + pkey->data, sizeof(link_name));
7366  if (strlen(link_name) > 0 && link_name[strlen(link_name) - 1] == ']') {
7368  if (strchr(link_name, '[') == NULL)
7369  return DB_INVALID_LINK;
7370  link_idx = atoi(strchr(link_name, '[') + 1);
7371  *strchr(link_name, '[') = 0;
7372  if (db_find_key(hDB, 0, link_name, &hkeylink) != DB_SUCCESS)
7373  return DB_INVALID_LINK;
7374  return db_set_data_index1(hDB, hkeylink, data, buf_size, link_idx, type, FALSE);
7375  }
7376  }
7377 
7378  status = db_check_set_data_locked(pheader, pkey, data, buf_size, num_values, type, "db_set_data1", &msg);
7379 
7380  if (status != DB_SUCCESS) {
7382  if (msg)
7383  db_flush_msg(&msg);
7384  return status;
7385  }
7386 
7387  db_allow_write_locked(&_database[hDB - 1], "db_set_data1");
7388 
7389  status = db_set_data_wlocked(pheader, pkey, data, buf_size, num_values, type, "db_set_data1", &msg);
7390 
7391  if (status != DB_SUCCESS) {
7393  if (msg)
7394  db_flush_msg(&msg);
7395  return status;
7396  }
7397 
7399  if (msg)
7400  db_flush_msg(&msg);
7401 
7402  }
7403 #endif /* LOCAL_ROUTINES */
7404 
7405  return DB_SUCCESS;
7406 }
INT db_set_data_index1(HNDLE hDB, HNDLE hKey, const void *data, INT data_size, INT idx, DWORD type, BOOL bNotify)
Definition: odb.cxx:7822
#define RPC_DB_SET_DATA1
Definition: mrpc.h:95
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_data_index()

INT EXPRT db_set_data_index ( HNDLE  hDB,
HNDLE  hKey,
const void *  data,
INT  data_size,
INT  idx,
DWORD  type 
)

dox Set key data for a key which contains an array of values.

This function sets individual values of a key containing an array. If the index is larger than the array size, the array is extended and the intermediate values are set to zero.

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
dataPointer to single value of data.
data_size
idxSize of single data element.
typeType of key, one of TID_xxx (see Midas_Data_Types).
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_NO_ACCESS, DB_TYPE_MISMATCH

Definition at line 7642 of file odb.cxx.

7643 {
7644  if (rpc_is_remote())
7645  return rpc_call(RPC_DB_SET_DATA_INDEX, hDB, hKey, data, data_size, idx, type);
7646 
7647 #ifdef LOCAL_ROUTINES
7648  {
7649  DATABASE_HEADER *pheader;
7650  KEY *pkey;
7651  char link_name[256];
7652  int link_idx;
7653  HNDLE hkeylink;
7654  int status;
7655 
7656  if (hDB > _database_entries || hDB <= 0) {
7657  cm_msg(MERROR, "db_set_data_index", "invalid database handle");
7658  return DB_INVALID_HANDLE;
7659  }
7660 
7661  if (!_database[hDB - 1].attached) {
7662  cm_msg(MERROR, "db_set_data_index", "invalid database handle");
7663  return DB_INVALID_HANDLE;
7664  }
7665 
7666  if (hKey < (int) sizeof(DATABASE_HEADER)) {
7667  cm_msg(MERROR, "db_set_data_index", "invalid key handle");
7668  return DB_INVALID_HANDLE;
7669  }
7670 
7672  db_err_msg* msg = NULL;
7673 
7674  pheader = _database[hDB - 1].database_header;
7675 
7676  /* check if hKey argument is correct */
7677  if (!db_validate_hkey(pheader, hKey)) {
7679  return DB_INVALID_HANDLE;
7680  }
7681 
7682  pkey = (KEY *) ((char *) pheader + hKey);
7683 
7684  /* check for write access */
7685  if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
7687  return DB_NO_ACCESS;
7688  }
7689 
7690  /* check for link to array index */
7691  if (pkey->type == TID_LINK) {
7692  strlcpy(link_name, (char *) pheader + pkey->data, sizeof(link_name));
7693  if (strlen(link_name) > 0 && link_name[strlen(link_name) - 1] == ']') {
7695  if (strchr(link_name, '[') == NULL)
7696  return DB_INVALID_LINK;
7697  link_idx = atoi(strchr(link_name, '[') + 1);
7698  *strchr(link_name, '[') = 0;
7699  if (db_find_key(hDB, 0, link_name, &hkeylink) != DB_SUCCESS)
7700  return DB_INVALID_LINK;
7701  return db_set_data_index(hDB, hkeylink, data, data_size, link_idx, type);
7702  }
7703  }
7704 
7705  status = db_check_set_data_index_locked(pheader, pkey, idx, data, data_size, type, "db_set_data_index", &msg);
7706 
7707  if (status != DB_SUCCESS) {
7709  if (msg)
7710  db_flush_msg(&msg);
7711  return status;
7712  }
7713 
7714  db_allow_write_locked(&_database[hDB-1], "db_set_data_index");
7715 
7716  status = db_set_data_index_wlocked(pheader, pkey, idx, data, data_size, type, "db_set_data_index", &msg);
7717 
7718  if (status != DB_SUCCESS) {
7720  if (msg)
7721  db_flush_msg(&msg);
7722  return status;
7723  }
7724 
7725  db_notify_clients_locked(pheader, hDB, hKey, idx, TRUE, &msg);
7727  if (msg)
7728  db_flush_msg(&msg);
7729 
7730  }
7731 #endif /* LOCAL_ROUTINES */
7732 
7733  return DB_SUCCESS;
7734 }
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)
Definition: odb.cxx:7051
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)
Definition: odb.cxx:7142
#define RPC_DB_SET_DATA_INDEX
Definition: mrpc.h:67
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_data_index1()

INT EXPRT db_set_data_index1 ( HNDLE  hDB,
HNDLE  hKey,
const void *  data,
INT  data_size,
INT  idx,
DWORD  type,
BOOL  bNotify 
)

dox

Definition at line 7822 of file odb.cxx.

7849 {
7850  if (rpc_is_remote())
7851  return rpc_call(RPC_DB_SET_DATA_INDEX1, hDB, hKey, data, data_size, idx, type, bNotify);
7852 
7853 #ifdef LOCAL_ROUTINES
7854  {
7855  DATABASE_HEADER *pheader;
7856  KEY *pkey;
7857  int status;
7858 
7859  if (hDB > _database_entries || hDB <= 0) {
7860  cm_msg(MERROR, "db_set_data_index1", "invalid database handle");
7861  return DB_INVALID_HANDLE;
7862  }
7863 
7864  if (!_database[hDB - 1].attached) {
7865  cm_msg(MERROR, "db_set_data_index1", "invalid database handle");
7866  return DB_INVALID_HANDLE;
7867  }
7868 
7869  if (hKey < (int) sizeof(DATABASE_HEADER)) {
7870  cm_msg(MERROR, "db_set_data_index1", "invalid key handle");
7871  return DB_INVALID_HANDLE;
7872  }
7873 
7875  db_err_msg* msg = NULL;
7876 
7877  pheader = _database[hDB - 1].database_header;
7878 
7879  /* check if hKey argument is correct */
7880  if (!db_validate_hkey(pheader, hKey)) {
7882  return DB_INVALID_HANDLE;
7883  }
7884 
7885  pkey = (KEY *) ((char *) pheader + hKey);
7886 
7887  status = db_check_set_data_index_locked(pheader, pkey, idx, data, data_size, type, "db_set_data_index1", &msg);
7888 
7889  if (status != DB_SUCCESS) {
7891  if (msg)
7892  db_flush_msg(&msg);
7893  return status;
7894  }
7895 
7896  db_allow_write_locked(&_database[hDB - 1], "db_set_data_index1");
7897 
7898  status = db_set_data_index_wlocked(pheader, pkey, idx, data, data_size, type, "db_set_data_index1", &msg);
7899 
7900  if (status != DB_SUCCESS) {
7902  if (msg)
7903  db_flush_msg(&msg);
7904  return status;
7905  }
7906 
7907  if (bNotify)
7908  db_notify_clients_locked(pheader, hDB, hKey, idx, TRUE, &msg);
7909 
7911  if (msg)
7912  db_flush_msg(&msg);
7913 
7914  }
7915 #endif /* LOCAL_ROUTINES */
7916 
7917  return DB_SUCCESS;
7918 }
#define RPC_DB_SET_DATA_INDEX1
Definition: mrpc.h:85
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_data_index_wlocked()

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 
)
static

Definition at line 7051 of file odb.cxx.

7052 {
7053  /* increase key size if necessary */
7054  if (idx >= pkey->num_values || pkey->item_size == 0) {
7055  // FIXME: validate pkey->data
7056  pkey->data = (POINTER_T) realloc_data(pheader, (char *) pheader + pkey->data, pkey->total_size, data_size * (idx + 1), caller);
7057 
7058  if (pkey->data == 0) {
7059  pkey->total_size = 0;
7060  pkey->num_values = 0;
7061  db_msg(msg, MERROR, caller, "Cannot reallocate \"%s\" with new num_values %d and new size %d bytes, online database full", db_get_path_locked(pheader, pkey).c_str(), idx + 1, data_size * (idx + 1));
7062  return DB_FULL;
7063  }
7064 
7065  pkey->data -= (POINTER_T) pheader;
7066  if (!pkey->item_size)
7067  pkey->item_size = data_size;
7068  pkey->total_size = data_size * (idx + 1);
7069  pkey->num_values = idx + 1;
7070  }
7071 
7072 #if 0
7073  /* cut strings which are too long */
7074  if ((type == TID_STRING || type == TID_LINK) && (int) strlen((char *) data) + 1 > pkey->item_size)
7075  *((char *) data + pkey->item_size - 1) = 0;
7076 
7077  /* copy data */
7078  memcpy((char *) pheader + pkey->data + idx * pkey->item_size, data, pkey->item_size);
7079 #endif
7080 
7081  if ((type == TID_STRING || type == TID_LINK)) {
7082  /* cut strings which are too long */
7083  strlcpy((char *) pheader + pkey->data + idx * pkey->item_size, (char*)data, pkey->item_size);
7084  } else {
7085  /* copy data */
7086  memcpy((char *) pheader + pkey->data + idx * pkey->item_size, data, pkey->item_size);
7087  }
7088 
7089  /* update time */
7090  pkey->last_written = ss_time();
7091 
7092  return DB_SUCCESS;
7093 }
static void * realloc_data(DATABASE_HEADER *pheader, void *address, INT old_size, INT new_size, const char *caller)
Definition: odb.cxx:532
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_data_wlocked()

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 
)
static

Set key data, adjust number of values if previous data has different size.

Parameters
pkeyKey to change
idxData index to change, "-1" means the whole array of data
dataBuffer from which data gets copied to.
data_sizeSize of data buffer.
num_valuesNumber of data values (for arrays).
typeType of key, one of TID_xxx (see Midas_Data_Types).
Returns
DB_SUCCESS, DB_FULL

Definition at line 7008 of file odb.cxx.

7009 {
7010  /* if no buf_size given (Java!), calculate it */
7011  if (data_size == 0)
7012  data_size = pkey->item_size * num_values;
7013 
7014  /* resize data size if necessary */
7015  if (pkey->total_size != data_size) {
7016  // FIXME: validate pkey->data!
7017  pkey->data = (POINTER_T) realloc_data(pheader, (char *) pheader + pkey->data, pkey->total_size, data_size, caller);
7018 
7019  if (pkey->data == 0) {
7020  pkey->total_size = 0;
7021  db_msg(msg, MERROR, caller, "Cannot reallocate \"%s\" with new size %d bytes, online database full", db_get_path_locked(pheader, pkey).c_str(), data_size);
7022  return DB_FULL;
7023  }
7024 
7025  pkey->data -= (POINTER_T) pheader;
7026  pkey->total_size = data_size;
7027  }
7028 
7029  /* set number of values */
7030  pkey->num_values = num_values;
7031 
7032  if (type == TID_STRING || type == TID_LINK)
7033  pkey->item_size = data_size / num_values;
7034  else
7035  pkey->item_size = rpc_tid_size(type);
7036 
7037  if ((type == TID_STRING || type == TID_LINK) && pkey->num_values == 1) {
7038  /* copy string up to NUL termination */
7039  strlcpy((char *) pheader + pkey->data, (const char*)data, data_size);
7040  } else {
7041  /* copy data */
7042  memcpy((char *) pheader + pkey->data, data, data_size);
7043  }
7044 
7045  /* update time */
7046  pkey->last_written = ss_time();
7047 
7048  return DB_SUCCESS;
7049 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_link_data()

INT EXPRT db_set_link_data ( HNDLE  hDB,
HNDLE  hKey,
const void *  data,
INT  buf_size,
INT  num_values,
DWORD  type 
)

Same as db_set_data, but it does not follow a link to an array index

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
dataBuffer from which data gets copied to.
buf_sizeSize of data buffer.
num_valuesNumber of data values (for arrays).
typeType of key, one of TID_xxx (see Midas_Data_Types).
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_TRUNCATED

Definition at line 7419 of file odb.cxx.

7420 {
7421  if (rpc_is_remote())
7422  return rpc_call(RPC_DB_SET_LINK_DATA, hDB, hKey, data, buf_size, num_values, type);
7423 
7424 #ifdef LOCAL_ROUTINES
7425  {
7426  DATABASE_HEADER *pheader;
7427  KEY *pkey;
7428  int status;
7429 
7430  if (hDB > _database_entries || hDB <= 0) {
7431  cm_msg(MERROR, "db_set_data", "invalid database handle");
7432  return DB_INVALID_HANDLE;
7433  }
7434 
7435  if (!_database[hDB - 1].attached) {
7436  cm_msg(MERROR, "db_set_data", "invalid database handle");
7437  return DB_INVALID_HANDLE;
7438  }
7439 
7440  if (hKey < (int) sizeof(DATABASE_HEADER)) {
7441  cm_msg(MERROR, "db_set_data", "invalid key handle");
7442  return DB_INVALID_HANDLE;
7443  }
7444 
7445  if (num_values == 0)
7446  return DB_INVALID_PARAM;
7447 
7449  db_err_msg* msg = NULL;
7450 
7451  pheader = _database[hDB - 1].database_header;
7452 
7453  /* check if hKey argument is correct */
7454  if (!db_validate_hkey(pheader, hKey)) {
7456  return DB_INVALID_HANDLE;
7457  }
7458 
7459  pkey = (KEY *) ((char *) pheader + hKey);
7460 
7461  status = db_check_set_data_locked(pheader, pkey, data, buf_size, num_values, type, "db_set_link_data", &msg);
7462 
7463  if (status != DB_SUCCESS) {
7465  if (msg)
7466  db_flush_msg(&msg);
7467  return status;
7468  }
7469 
7470  db_allow_write_locked(&_database[hDB - 1], "db_set_link_data");
7471 
7472  status = db_set_data_wlocked(pheader, pkey, data, buf_size, num_values, type, "db_set_link_data", &msg);
7473 
7474  if (status != DB_SUCCESS) {
7476  if (msg)
7477  db_flush_msg(&msg);
7478  return status;
7479  }
7480 
7481  db_notify_clients_locked(pheader, hDB, hKey, -1, TRUE, &msg);
7483  if (msg)
7484  db_flush_msg(&msg);
7485 
7486  }
7487 #endif /* LOCAL_ROUTINES */
7488 
7489  return DB_SUCCESS;
7490 }
#define RPC_DB_SET_LINK_DATA
Definition: mrpc.h:93
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_link_data_index()

INT EXPRT db_set_link_data_index ( HNDLE  hDB,
HNDLE  hKey,
const void *  data,
INT  data_size,
INT  idx,
DWORD  type 
)

Same as db_set_data_index, but does not follow links.

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
dataPointer to single value of data.
data_size
idxSize of single data element.
typeType of key, one of TID_xxx (see Midas_Data_Types).
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_NO_ACCESS, DB_TYPE_MISMATCH

Definition at line 7748 of file odb.cxx.

7749 {
7750  if (rpc_is_remote())
7751  return rpc_call(RPC_DB_SET_LINK_DATA_INDEX, hDB, hKey, data, data_size, idx, type);
7752 
7753 #ifdef LOCAL_ROUTINES
7754  {
7755  DATABASE_HEADER *pheader;
7756  KEY *pkey;
7757  int status;
7758 
7759  if (hDB > _database_entries || hDB <= 0) {
7760  cm_msg(MERROR, "db_set_link_data_index", "invalid database handle");
7761  return DB_INVALID_HANDLE;
7762  }
7763 
7764  if (!_database[hDB - 1].attached) {
7765  cm_msg(MERROR, "db_set_link_data_index", "invalid database handle");
7766  return DB_INVALID_HANDLE;
7767  }
7768 
7769  if (hKey < (int) sizeof(DATABASE_HEADER)) {
7770  cm_msg(MERROR, "db_set_link_data_index", "invalid key handle");
7771  return DB_INVALID_HANDLE;
7772  }
7773 
7775  db_err_msg* msg = NULL;
7776 
7777  pheader = _database[hDB - 1].database_header;
7778 
7779  /* check if hKey argument is correct */
7780  if (!db_validate_hkey(pheader, hKey)) {
7782  return DB_INVALID_HANDLE;
7783  }
7784 
7785  pkey = (KEY *) ((char *) pheader + hKey);
7786 
7787  status = db_check_set_data_index_locked(pheader, pkey, idx, data, data_size, type, "db_set_link_data_index", &msg);
7788 
7789  if (status != DB_SUCCESS) {
7791  if (msg)
7792  db_flush_msg(&msg);
7793  return status;
7794  }
7795 
7796  db_allow_write_locked(&_database[hDB - 1], "db_set_link_data_index");
7797 
7798  status = db_set_data_index_wlocked(pheader, pkey, idx, data, data_size, type, "db_set_link_data_index", &msg);
7799 
7800  if (status != DB_SUCCESS) {
7802  if (msg)
7803  db_flush_msg(&msg);
7804  return status;
7805  }
7806 
7807  db_notify_clients_locked(pheader, hDB, hKey, idx, TRUE, &msg);
7809  if (msg)
7810  db_flush_msg(&msg);
7811 
7812  }
7813 #endif /* LOCAL_ROUTINES */
7814 
7815  return DB_SUCCESS;
7816 }
#define RPC_DB_SET_LINK_DATA_INDEX
Definition: mrpc.h:94
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_lock_timeout()

INT db_set_lock_timeout ( HNDLE  hDB,
int  timeout_millisec 
)

Definition at line 2652 of file odb.cxx.

2653 {
2654 #ifdef LOCAL_ROUTINES
2655 
2656  /* return zero if no ODB is open or we run remotely */
2657  if (_database_entries == 0)
2658  return 0;
2659 
2660  if (hDB > _database_entries || hDB <= 0) {
2661  cm_msg(MERROR, "db_set_lock_timeout", "invalid database handle %d, aborting...", hDB);
2662  fprintf(stderr, "db_set_lock_timeout: invalid database handle %d, aborting...\n", hDB);
2663  abort();
2664  return DB_INVALID_HANDLE;
2665  }
2666 
2667  if (timeout_millisec > 0) {
2668  _database[hDB - 1].timeout = timeout_millisec;
2669  }
2670 
2671  return _database[hDB - 1].timeout;
2672 #else
2673  return 0;
2674 #endif
2675 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_mode()

INT EXPRT db_set_mode ( HNDLE  hDB,
HNDLE  hKey,
WORD  mode,
BOOL  recurse 
)

Definition at line 8021 of file odb.cxx.

8046 {
8047  if (rpc_is_remote())
8048  return rpc_call(RPC_DB_SET_MODE, hDB, hKey, mode, recurse);
8049 
8050 #ifdef LOCAL_ROUTINES
8051  {
8052  DATABASE_HEADER *pheader;
8053  BOOL locked = FALSE;
8054 
8055  if (hDB > _database_entries || hDB <= 0) {
8056  cm_msg(MERROR, "db_set_mode", "invalid database handle");
8057  return DB_INVALID_HANDLE;
8058  }
8059 
8060  if (!_database[hDB - 1].attached) {
8061  cm_msg(MERROR, "db_set_mode", "invalid database handle");
8062  return DB_INVALID_HANDLE;
8063  }
8064 
8065  if (recurse < 2) {
8067  locked = TRUE;
8068  }
8069 
8070  pheader = _database[hDB - 1].database_header;
8071 
8072  db_err_msg* msg = NULL;
8073  int status = 0;
8074 
8075  KEY *pkey = (KEY*)db_get_pkey(pheader, hKey, &status, "db_set_mode", &msg);
8076 
8077  if (!pkey) {
8078  if (locked) {
8080  if (msg)
8081  db_flush_msg(&msg);
8082  return status;
8083  }
8084  }
8085 
8086  db_allow_write_locked(&_database[hDB-1], "db_set_mode");
8087 
8088  status = db_set_mode_wlocked(pheader, pkey, mode, recurse, &msg);
8089 
8090  if (locked) {
8092  if (msg)
8093  db_flush_msg(&msg);
8094  }
8095 
8096  return status;
8097  }
8098 #endif /* LOCAL_ROUTINES */
8099 
8100  return DB_SUCCESS;
8101 }
#define RPC_DB_SET_MODE
Definition: mrpc.h:68
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_mode_wlocked()

static int db_set_mode_wlocked ( DATABASE_HEADER pheader,
KEY pkey,
WORD  mode,
int  recurse,
db_err_msg **  msg 
)
static

Definition at line 7973 of file odb.cxx.

7993 {
7994  /* resolve links */
7995  if (pkey->type == TID_LINK) {
7996  int status;
7997  pkey = (KEY*)db_resolve_link_locked(pheader, pkey, &status, msg);
7998  if (!pkey) {
7999  return status;
8000  }
8001  }
8002 
8003  if (pkey->type == TID_KEY && recurse) {
8004  // drop "const" from KEY* we are permitted to write to ODB!
8005  KEY* psubkey = (KEY*)db_enum_first_locked(pheader, pkey, msg);
8006  while (psubkey) {
8007  db_set_mode_wlocked(pheader, psubkey, mode, recurse+1, msg);
8008  psubkey = (KEY*)db_enum_next_locked(pheader, pkey, psubkey, msg);
8009  }
8010  }
8011 
8012  /* now set mode */
8013  pkey->access_mode = mode;
8014 
8015  return DB_SUCCESS;
8016 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_num_values()

INT EXPRT db_set_num_values ( HNDLE  hDB,
HNDLE  hKey,
INT  num_values 
)

dox

Definition at line 7496 of file odb.cxx.

7516 {
7517  if (rpc_is_remote())
7518  return rpc_call(RPC_DB_SET_NUM_VALUES, hDB, hKey, num_values);
7519 
7520 #ifdef LOCAL_ROUTINES
7521  {
7522  DATABASE_HEADER *pheader;
7523  KEY *pkey;
7524  INT new_size;
7525 
7526  if (hDB > _database_entries || hDB <= 0) {
7527  cm_msg(MERROR, "db_set_num_values", "invalid database handle");
7528  return DB_INVALID_HANDLE;
7529  }
7530 
7531  if (!_database[hDB - 1].attached) {
7532  cm_msg(MERROR, "db_set_num_values", "invalid database handle");
7533  return DB_INVALID_HANDLE;
7534  }
7535 
7536  if (hKey < (int) sizeof(DATABASE_HEADER)) {
7537  cm_msg(MERROR, "db_set_num_values", "invalid key handle");
7538  return DB_INVALID_HANDLE;
7539  }
7540 
7541  if (num_values <= 0) {
7542  cm_msg(MERROR, "db_set_num_values", "invalid num_values %d", num_values);
7543  return DB_INVALID_PARAM;
7544  }
7545 
7546  if (num_values == 0)
7547  return DB_INVALID_PARAM;
7548 
7550  db_err_msg* msg = NULL;
7551 
7552  pheader = _database[hDB - 1].database_header;
7553 
7554  /* check if hKey argument is correct */
7555  if (!db_validate_hkey(pheader, hKey)) {
7557  return DB_INVALID_HANDLE;
7558  }
7559 
7560  pkey = (KEY *) ((char *) pheader + hKey);
7561 
7562  /* check for write access */
7563  if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
7565  return DB_NO_ACCESS;
7566  }
7567 
7568  /* keys cannot contain data */
7569  if (pkey->type == TID_KEY) {
7571  cm_msg(MERROR, "db_set_num_values", "Key cannot contain data");
7572  return DB_TYPE_MISMATCH;
7573  }
7574 
7575  if (pkey->total_size != pkey->item_size * pkey->num_values) {
7577  cm_msg(MERROR, "db_set_num_values", "Corrupted key");
7578  return DB_CORRUPTED;
7579  }
7580 
7581  if (pkey->item_size == 0) {
7583  cm_msg(MERROR, "db_set_num_values", "Cannot resize array with item_size equal to zero");
7584  return DB_INVALID_PARAM;
7585  }
7586 
7587  db_allow_write_locked(&_database[hDB - 1], "db_set_num_values");
7588 
7589  /* resize data size if necessary */
7590  if (pkey->num_values != num_values) {
7591  new_size = pkey->item_size * num_values;
7592 
7593  pkey->data = (POINTER_T) realloc_data(pheader, (char *) pheader + pkey->data, pkey->total_size, new_size, "db_set_num_values");
7594 
7595  if (pkey->data == 0) {
7596  pkey->total_size = 0;
7597  pkey->num_values = 0;
7598  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_locked(pheader, pkey).c_str(), num_values, new_size);
7600  if (msg)
7601  db_flush_msg(&msg);
7602  return DB_FULL;
7603  }
7604 
7605  pkey->data -= (POINTER_T) pheader;
7606  pkey->total_size = new_size;
7607  pkey->num_values = num_values;
7608  }
7609 
7610  /* update time */
7611  pkey->last_written = ss_time();
7612 
7613  db_notify_clients_locked(pheader, hDB, hKey, -1, TRUE, &msg);
7615  if (msg)
7616  db_flush_msg(&msg);
7617 
7618  }
7619 #endif /* LOCAL_ROUTINES */
7620 
7621  return DB_SUCCESS;
7622 }
#define RPC_DB_SET_NUM_VALUES
Definition: mrpc.h:88
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_record()

INT EXPRT db_set_record ( HNDLE  hDB,
HNDLE  hKey,
void *  data,
INT  buf_size,
INT  align 
)

Copy a set of keys from local memory to the database.

An ODB sub-tree can be mapped to a C structure automatically via a hot-link using the function db_open_record() or manually with this function. Problems might occur if the ODB sub-tree contains values which don't match the C structure. Although the structure size is checked against the sub-tree size, no checking can be done if the type and order of the values in the structure are the same than those in the ODB sub-tree. Therefore it is recommended to use the function db_create_record() before using this function.

...
memset(&lazyst,0,size);
if (db_find_key(hDB, pLch->hKey, "Statistics",&hKeyst) == DB_SUCCESS)
else
cm_msg(MERROR,"task","record %s/statistics not found", pLch->name)
...
LAZY_STATISTICS lazyst
Definition: lazylogger.cxx:193
HNDLE hKeyst
Definition: lazylogger.cxx:209
Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key where search starts, zero for root.
dataPointer where data is stored.
buf_sizeSize of data structure, must be obtained via sizeof(RECORD-NAME).
alignByte alignment calculated by the stub and passed to the rpc side to align data according to local machine. Must be zero when called from user level.
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_TYPE_MISMATCH, DB_STRUCT_SIZE_MISMATCH

Definition at line 12295 of file odb.cxx.

12296 {
12297  if (rpc_is_remote()) {
12298  align = ss_get_struct_align();
12299  return rpc_call(RPC_DB_SET_RECORD, hDB, hKey, data, buf_size, align);
12300  }
12301 #ifdef LOCAL_ROUTINES
12302  {
12303  KEY key;
12304  INT convert_flags;
12305  INT total_size;
12306  void *pdata;
12307 
12308  convert_flags = 0;
12309 
12310  if (!align)
12311  align = ss_get_struct_align();
12312  else {
12313  /* only convert data if called remotely, as indicated by align != 0 */
12314  if (rpc_is_mserver()) {
12315  convert_flags = rpc_get_convert_flags();
12316  }
12317  }
12318 
12319  /* check if key has subkeys */
12320  db_get_key(hDB, hKey, &key);
12321  if (key.type != TID_KEY) {
12322  /* copy single key */
12323  if (key.item_size * key.num_values != buf_size) {
12324  cm_msg(MERROR, "db_set_record", "struct size mismatch for \"%s\"", key.name);
12325  return DB_STRUCT_SIZE_MISMATCH;
12326  }
12327 
12328  if (convert_flags) {
12329  if (key.num_values > 1)
12331  else
12332  rpc_convert_single(data, key.type, 0, convert_flags);
12333  }
12334 
12336  return DB_SUCCESS;
12337  }
12338 
12339  /* check record size */
12340  db_get_record_size(hDB, hKey, align, &total_size);
12341  if (total_size != buf_size) {
12342  cm_msg(MERROR, "db_set_record", "struct size mismatch for \"%s\"", key.name);
12343  return DB_STRUCT_SIZE_MISMATCH;
12344  }
12345 
12346  /* set subkey data */
12347  pdata = data;
12348  total_size = 0;
12349 
12351  db_err_msg* msg = NULL;
12352  db_allow_write_locked(&_database[hDB-1], "db_set_record");
12353  db_recurse_record_tree_locked(hDB, hKey, &pdata, &total_size, align, NULL, TRUE, convert_flags, &msg);
12355  if (msg)
12356  db_flush_msg(&msg);
12357  }
12358 #endif /* LOCAL_ROUTINES */
12359 
12360  return DB_SUCCESS;
12361 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_record2()

INT EXPRT db_set_record2 ( HNDLE  hdb,
HNDLE  hKey,
void *  data,
INT  buf_size,
INT  align,
const char *  rec_str 
)

◆ db_set_value()

INT EXPRT db_set_value ( HNDLE  hDB,
HNDLE  hKeyRoot,
const char *  key_name,
const void *  data,
INT  data_size,
INT  num_values,
DWORD  type 
)

dox Set value of a single key.

The function sets a single value or a whole array to a ODB key. Since the data buffer is of type void, no type checking can be performed by the compiler. Therefore the type has to be explicitly supplied, which is checked against the type stored in the ODB. key_name can contain the full path of a key (like: "/Equipment/Trigger/Settings/Level1") while hkey is zero which refers to the root, or hkey can refer to a sub-directory (like /Equipment/Trigger) and key_name is interpreted relative to that directory like "Settings/Level1".

INT level1;
db_set_value(hDB, 0, "/Equipment/Trigger/Settings/Level1",
&level1, sizeof(level1), 1, TID_INT32);
Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyRootHandle for key where search starts, zero for root.
key_nameName of key to search, can contain directories.
dataAddress of data.
data_sizeSize of data (in bytes).
num_valuesNumber of data elements.
typeType of key, one of TID_xxx (see Midas_Data_Types)
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_NO_ACCESS, DB_TYPE_MISMATCH

Definition at line 5251 of file odb.cxx.

5253 {
5254  if (rpc_is_remote())
5255  return rpc_call(RPC_DB_SET_VALUE, hDB, hKeyRoot, key_name, data, data_size, num_values, type);
5256 
5257 #ifdef LOCAL_ROUTINES
5258  {
5259  INT status;
5260 
5261  if (num_values == 0)
5262  return DB_INVALID_PARAM;
5263 
5265 
5266  DATABASE_HEADER* pheader = _database[hDB - 1].database_header;
5267 
5268  db_allow_write_locked(&_database[hDB-1], "db_set_value");
5269 
5270  db_err_msg* msg = NULL;
5271 
5272  KEY* pkey_root = (KEY*)db_get_pkey(pheader, hKeyRoot, &status, "db_set_value", &msg);
5273 
5274  if (pkey_root) {
5275  status = db_set_value_wlocked(pheader, hDB, pkey_root, key_name, data, data_size, num_values, type, &msg);
5276  }
5277 
5279  if (msg)
5280  db_flush_msg(&msg);
5281 
5282  return status;
5283  }
5284 #endif /* LOCAL_ROUTINES */
5285 
5286  return DB_SUCCESS;
5287 }
#define RPC_DB_SET_VALUE
Definition: mrpc.h:57
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_value_index()

INT EXPRT db_set_value_index ( HNDLE  hDB,
HNDLE  hKeyRoot,
const char *  key_name,
const void *  data,
INT  data_size,
INT  idx,
DWORD  type,
BOOL  trunc 
)

Set single value of an array.

The function sets a single value of an ODB key which is an array. key_name can contain the full path of a key (like: "/Equipment/Trigger/Settings/Level1") while hkey is zero which refers to the root, or hkey can refer to a sub-directory (like /Equipment/Trigger) and key_name is interpreted relative to that directory like "Settings/Level1".

INT level1;
db_set_value_index(hDB, 0, "/Equipment/Trigger/Settings/Level1",
&level1, sizeof(level1), 15, TID_INT32, FALSE);
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)
Definition: odb.cxx:5355
Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyRootHandle for key where search starts, zero for root.
key_nameName of key to search, can contain directories.
dataAddress of data.
data_sizeSize of data (in bytes).
indexArray index of value.
typeType of key, one of TID_xxx (see Midas_Data_Types)
truncateTruncate array to current index if TRUE
Returns
<same as db_set_data_index>

Definition at line 5355 of file odb.cxx.

5357 {
5358  int status;
5359  HNDLE hkey;
5360 
5361  status = db_find_key(hDB, hKeyRoot, key_name, &hkey);
5362  if (!hkey) {
5363  status = db_create_key(hDB, hKeyRoot, key_name, type);
5364  status = db_find_key(hDB, hKeyRoot, key_name, &hkey);
5365  if (status != DB_SUCCESS)
5366  return status;
5367  } else
5368  if (trunc) {
5369  status = db_set_num_values(hDB, hkey, idx + 1);
5370  if (status != DB_SUCCESS)
5371  return status;
5372  }
5373 
5374  return db_set_data_index(hDB, hkey, data, data_size, idx, type);
5375 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_value_string()

INT EXPRT db_set_value_string ( HNDLE  hDB,
HNDLE  hKeyRoot,
const char *  key_name,
const std::string *  s 
)

Definition at line 14008 of file odb.cxx.

14009 {
14010  assert(s != NULL);
14011  int size = s->length() + 1; // 1 byte for final \0
14012  //printf("db_set_value_string: key_name [%s], string [%s], size %d\n", key_name, s->c_str(), size);
14013  return db_set_value(hDB, hKeyRoot, key_name, s->c_str(), size, 1, TID_STRING);
14014 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_value_wlocked()

static int db_set_value_wlocked ( DATABASE_HEADER pheader,
HNDLE  hDB,
KEY pkey_root,
const char *  key_name,
const void *  data,
INT  data_size,
INT  num_values,
DWORD  type,
db_err_msg **  msg 
)
static

Definition at line 5290 of file odb.cxx.

5291 {
5292  INT status;
5293 
5294  if (num_values == 0)
5295  return DB_INVALID_PARAM;
5296 
5297  KEY* pkey = (KEY*)db_find_pkey_locked(pheader, pkey_root, key_name, &status, msg);
5298 
5299  if (!pkey) {
5300  status = db_create_key_wlocked(pheader, pkey_root, key_name, type, &pkey, msg);
5301  if (status != DB_SUCCESS && status != DB_CREATED)
5302  return status;
5303  }
5304 
5305  if (data_size == 0) {
5306  db_msg(msg, MERROR, "db_set_value", "zero data size not allowed");
5307  return DB_TYPE_MISMATCH;
5308  }
5309 
5310  if (type != TID_STRING && type != TID_LINK && data_size != rpc_tid_size(type) * num_values) {
5311  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);
5312  return DB_TYPE_MISMATCH;
5313  }
5314 
5315  status = db_check_set_data_locked(pheader, pkey, data, data_size, num_values, type, "db_set_value", msg);
5316 
5317  if (status != DB_SUCCESS)
5318  return status;
5319 
5320  status = db_set_data_wlocked(pheader, pkey, data, data_size, num_values, type, "db_set_value", msg);
5321 
5322  if (status != DB_SUCCESS)
5323  return status;
5324 
5325  db_notify_clients_locked(pheader, hDB, db_pkey_to_hkey(pheader, pkey), -1, TRUE, msg);
5326 
5327  return DB_SUCCESS;
5328 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_watchdog_params()

void db_set_watchdog_params ( DWORD  timeout)

Definition at line 2966 of file odb.cxx.

2967 {
2968  /* set watchdog flag of all open databases */
2969  for (int i = _database_entries; i > 0; i--) {
2970 
2972 
2973  DATABASE* pdb = &_database[i - 1];
2974 
2975  if (!pdb->attached) {
2977  continue;
2978  }
2979 
2980  DATABASE_CLIENT *pclient = db_get_my_client_locked(pdb);
2981 
2982  db_allow_write_locked(pdb, "db_set_watchdog_params");
2983 
2984  /* clear entry from client structure in buffer header */
2985  pclient->watchdog_timeout = timeout;
2986 
2987  /* show activity */
2988  pclient->last_activity = ss_millitime();
2989 
2991  }
2992 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_show_mem()

INT db_show_mem ( HNDLE  hDB,
char **  result,
BOOL  verbose 
)

Definition at line 673 of file odb.cxx.

674 {
675  INT total_size_key, total_size_data;
676 
677  struct print_key_info_buf buf;
678  buf.buf = NULL;
679  buf.used = 0;
680  buf.alloc_size = 0;
681 
683 
685 
686  char str[256];
687 
688  sprintf(str, "Database header size is 0x%04X, all following values are offset by this!\n", (int)sizeof(DATABASE_HEADER));
689  add_to_buf(&buf, str);
690  sprintf(str, "Key area 0x00000000 - 0x%08X, size %d bytes\n", pheader->key_size - 1, pheader->key_size);
691  add_to_buf(&buf, str);
692  sprintf(str, "Data area 0x%08X - 0x%08X, size %d bytes\n\n", pheader->key_size, pheader->key_size + pheader->data_size, pheader->data_size);
693  add_to_buf(&buf, str);
694 
695  add_to_buf(&buf, "Keylist:\n");
696  add_to_buf(&buf, "--------\n");
697  total_size_key = 0;
698 
699  if (!db_validate_key_offset(pheader, pheader->first_free_key)) {
700  add_to_buf(&buf, "ODB is corrupted: pheader->first_free_key is invalid\n");
702  if (result) {
703  *result = buf.buf;
704  } else {
705  free(buf.buf);
706  }
707  return DB_CORRUPTED;
708  }
709 
710  FREE_DESCRIP *pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_key);
711 
712  while ((POINTER_T) pfree != (POINTER_T) pheader) {
713  total_size_key += pfree->size;
714  sprintf(str, "Free block at 0x%08X, size 0x%08X, next 0x%08X\n",
715  (int) ((POINTER_T) pfree - (POINTER_T) pheader - sizeof(DATABASE_HEADER)),
716  pfree->size, pfree->next_free ? (int) (pfree->next_free - sizeof(DATABASE_HEADER)) : 0);
717  add_to_buf(&buf, str);
718  if (!db_validate_key_offset(pheader, pfree->next_free)) {
719  add_to_buf(&buf, "ODB is corrupted: next_free is invalid!");
720  break;
721  }
722  pfree = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
723  }
724 
725  sprintf(str, "\nFree Key area: %d bytes out of %d bytes\n", total_size_key, pheader->key_size);
726  add_to_buf(&buf, str);
727 
728  add_to_buf(&buf, "\nData:\n");
729  add_to_buf(&buf, "-----\n");
730  total_size_data = 0;
731 
732  if (!db_validate_data_offset(pheader, pheader->first_free_data)) {
733  add_to_buf(&buf, "ODB is corrupted: pheader->first_free_data is invalid\n");
735  if (result) {
736  *result = buf.buf;
737  } else {
738  free(buf.buf);
739  }
740  return DB_CORRUPTED;
741  }
742 
743  pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_data);
744 
745  while ((POINTER_T) pfree != (POINTER_T) pheader) {
746  total_size_data += pfree->size;
747  sprintf(str, "Free block at 0x%08X, size 0x%08X, next 0x%08X\n",
748  (int) ((POINTER_T) pfree - (POINTER_T) pheader - sizeof(DATABASE_HEADER)),
749  pfree->size, pfree->next_free ? (int) (pfree->next_free - sizeof(DATABASE_HEADER)) : 0);
750  add_to_buf(&buf, str);
751  if (!db_validate_data_offset(pheader, pfree->next_free)) {
752  add_to_buf(&buf, "ODB is corrupted: next_free is invalid!");
753  break;
754  }
755  pfree = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
756  }
757 
758  sprintf(str, "\nFree Data area: %d bytes out of %d bytes\n", total_size_data, pheader->data_size);
759  add_to_buf(&buf, str);
760 
761  sprintf(str, "\nFree: %1d (%1.1lf%%) keylist, %1d (%1.1lf%%) data\n",
762  total_size_key,
763  100 * (double) total_size_key / pheader->key_size,
764  total_size_data, 100 * (double) total_size_data / pheader->data_size);
765  add_to_buf(&buf, str);
766 
767  if (verbose) {
768  add_to_buf(&buf, "\n\n");
769  add_to_buf(&buf, "Key Data Size\n");
770  add_to_buf(&buf, "----------------------------\n");
771  db_scan_tree(hDB, pheader->root_key, 0, print_key_info, &buf);
772  }
773 
774  sprintf(str, "\nTotal ODB size: %d (0x%08X) Bytes, %lg MiB\n",
775  pheader->key_size + pheader->data_size, pheader->key_size + pheader->data_size,
776  ((pheader->key_size + pheader->data_size) / 1E6));
777  add_to_buf(&buf, str);
779 
780  if (result) {
781  *result = buf.buf;
782  } else {
783  free(buf.buf);
784  }
785 
786  return DB_SUCCESS;
787 }
static void add_to_buf(struct print_key_info_buf *buf, const char *s)
Definition: odb.cxx:623
static INT print_key_info(HNDLE hDB, HNDLE hKey, KEY *pkey, INT level, void *info)
Definition: odb.cxx:641
BOOL verbose
Definition: mana.cxx:255
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_sor()

MJsonNode *EXPRT db_sor ( HNDLE  hDB,
const char *  root_path 
)

Definition at line 14164 of file odb.cxx.

14165 {
14166  //printf("db_sor(%s)\n", root_path);
14167  assert(root_path != NULL);
14168  size_t root_path_len = strlen(root_path);
14169 #ifdef LOCAL_ROUTINES
14170  MJsonNode* sor = MJsonNode::MakeArray();
14171 
14172  /* lock database */
14174 
14175  DATABASE *pdb = &_database[hDB - 1];
14176  DATABASE_HEADER *pheader = pdb->database_header;
14177 
14178  /* list clients */
14179  for (int i = 0; i < pheader->max_client_index; i++) {
14180  DATABASE_CLIENT *pclient = &pheader->client[i];
14181  if (pclient->pid) {
14182  for (int j = 0; j < pclient->max_index; j++) {
14183  std::string path = db_get_path_locked(pheader, pclient->open_record[j].handle);
14184  if (path.length() < root_path_len)
14185  continue;
14186  if (strncmp(root_path, path.c_str(), root_path_len) != 0)
14187  continue;
14188  MJsonNode* c = MJsonNode::MakeObject();
14189  c->AddToObject("name", MJsonNode::MakeString(pclient->name));
14190  //c->AddToObject("handle", MJsonNode::MakeNumber(pclient->open_record[j].handle));
14191  c->AddToObject("access_mode", MJsonNode::MakeNumber(pclient->open_record[j].access_mode));
14192  c->AddToObject("flags", MJsonNode::MakeNumber(pclient->open_record[j].flags));
14193  c->AddToObject("path", MJsonNode::MakeString(path.c_str()));
14194  sor->AddToArray(c);
14195  }
14196  }
14197  }
14198 
14200 
14201  return sor;
14202 #else
14203  return MJsonNode::MakeNull();
14204 #endif
14205 }
WORD flags
Definition: msystem.h:406
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_sprintf() [1/2]

INT EXPRT db_sprintf ( char *  string,
const void *  data,
INT  data_size,
INT  idx,
DWORD  type 
)

dox Convert a database value to a string according to its type.

This function is a convenient way to convert a binary ODB value into a string depending on its type if is not known at compile time. If it is known, the normal sprintf() function can be used.

...
for (j=0 ; j<key.num_values ; j++)
{
db_sprintf(pbuf, pdata, key.item_size, j, key.type);
strcat(pbuf, "\n");
}
...
Parameters
stringoutput ASCII string of data. must be at least MAX_STRING_LENGTH bytes long.
dataValue data.
data_sizeSize of single data element.
idxIndex for array data.
typeType of key, one of TID_xxx (see Midas_Data_Types).
Returns
DB_SUCCESS

Definition at line 10847 of file odb.cxx.

10848 {
10849  if (data_size == 0)
10850  sprintf(string, "<NULL>");
10851  else
10852  switch (type) {
10853  case TID_UINT8:
10854  sprintf(string, "%d", *(((BYTE *) data) + idx));
10855  break;
10856  case TID_INT8:
10857  sprintf(string, "%d", *(((char *) data) + idx));
10858  break;
10859  case TID_CHAR:
10860  sprintf(string, "%c", *(((char *) data) + idx));
10861  break;
10862  case TID_UINT16:
10863  sprintf(string, "%u", *(((WORD *) data) + idx));
10864  break;
10865  case TID_INT16:
10866  sprintf(string, "%d", *(((short *) data) + idx));
10867  break;
10868  case TID_UINT32:
10869  sprintf(string, "%u", *(((DWORD *) data) + idx));
10870  break;
10871  case TID_INT32:
10872  sprintf(string, "%d", *(((INT *) data) + idx));
10873  break;
10874  case TID_UINT64:
10875  sprintf(string, "%llu", *(((UINT64 *) data) + idx));
10876  break;
10877  case TID_INT64:
10878  sprintf(string, "%lld", *(((INT64 *) data) + idx));
10879  break;
10880  case TID_BOOL:
10881  sprintf(string, "%c", *(((BOOL *) data) + idx) ? 'y' : 'n');
10882  break;
10883  case TID_FLOAT:
10884  if (ss_isnan(*(((float *) data) + idx)))
10885  sprintf(string, "NAN");
10886  else
10887  sprintf(string, "%.7g", *(((float *) data) + idx));
10888  break;
10889  case TID_DOUBLE:
10890  if (ss_isnan(*(((double *) data) + idx)))
10891  sprintf(string, "NAN");
10892  else
10893  sprintf(string, "%.16lg", *(((double *) data) + idx));
10894  break;
10895  case TID_BITFIELD:
10896  sprintf(string, "%u", *(((DWORD *) data) + idx));
10897  break;
10898  case TID_STRING:
10899  case TID_LINK:
10900  strlcpy(string, ((char *) data) + data_size * idx, MAX_STRING_LENGTH);
10901  break;
10902  default:
10903  sprintf(string, "<unknown>");
10904  break;
10905  }
10906 
10907  return DB_SUCCESS;
10908 }
unsigned char BYTE
Definition: mcstd.h:48
int ss_isnan(double x)
Definition: system.cxx:7900
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_sprintf() [2/2]

std::string EXPRT db_sprintf ( const void *  data,
INT  data_size,
INT  idx,
DWORD  type 
)

Convert a database value to a string according to its type.

This function is a convenient way to convert a binary ODB value into a string depending on its type if is not known at compile time. If it is known, the normal sprintf() function can be used.

...
for (j=0 ; j<key.num_values ; j++)
{
std::string s = db_sprintf(pdata, key.item_size, j, key.type);
}
...
Parameters
dataValue data.
data_sizeSize of single data element.
idxIndex for array data.
typeType of key, one of TID_xxx (see Midas_Data_Types).
Returns
string output ASCII string of data.

Definition at line 11091 of file odb.cxx.

11092 {
11093  if (data_size == 0) {
11094  return "<NULL>";
11095  } else {
11096  char buf[256];
11097  switch (type) {
11098  case TID_UINT8:
11099  sprintf(buf, "%d", *(((BYTE *) data) + idx));
11100  return buf;
11101  case TID_INT8:
11102  sprintf(buf, "%d", *(((char *) data) + idx));
11103  return buf;
11104  case TID_CHAR:
11105  sprintf(buf, "%c", *(((char *) data) + idx));
11106  return buf;
11107  case TID_UINT16:
11108  sprintf(buf, "%u", *(((WORD *) data) + idx));
11109  return buf;
11110  case TID_INT16:
11111  sprintf(buf, "%d", *(((short *) data) + idx));
11112  return buf;
11113  case TID_UINT32:
11114  sprintf(buf, "%u", *(((DWORD *) data) + idx));
11115  return buf;
11116  case TID_INT32:
11117  sprintf(buf, "%d", *(((INT *) data) + idx));
11118  return buf;
11119  case TID_UINT64:
11120  sprintf(buf, "%llu", *(((UINT64 *) data) + idx));
11121  return buf;
11122  case TID_INT64:
11123  sprintf(buf, "%lld", *(((INT64 *) data) + idx));
11124  return buf;
11125  case TID_BOOL:
11126  sprintf(buf, "%c", *(((BOOL *) data) + idx) ? 'y' : 'n');
11127  return buf;
11128  case TID_FLOAT:
11129  if (ss_isnan(*(((float *) data) + idx))) {
11130  return "NAN";
11131  } else {
11132  sprintf(buf, "%.7g", *(((float *) data) + idx));
11133  return buf;
11134  }
11135  case TID_DOUBLE:
11136  if (ss_isnan(*(((double *) data) + idx))) {
11137  return "NAN";
11138  } else {
11139  sprintf(buf, "%.16lg", *(((double *) data) + idx));
11140  return buf;
11141  }
11142  case TID_BITFIELD:
11143  sprintf(buf, "%u", *(((DWORD *) data) + idx));
11144  return buf;
11145  case TID_STRING:
11146  case TID_LINK:
11147  return (((char *) data) + data_size * idx);
11148  default:
11149  return "<unknown>";
11150  }
11151  }
11152 }
Here is the call graph for this function:

◆ db_sprintff() [1/2]

INT EXPRT db_sprintff ( char *  string,
const char *  format,
const void *  data,
INT  data_size,
INT  idx,
DWORD  type 
)

Same as db_sprintf, but with additional format parameter

Parameters
stringoutput ASCII string of data.
formatFormat specifier passed to sprintf()
dataValue data.
data_sizeSize of single data element.
idxIndex for array data.
typeType of key, one of TID_xxx (see Midas_Data_Types).
Returns
DB_SUCCESS

Definition at line 10923 of file odb.cxx.

10924 {
10925  if (data_size == 0)
10926  sprintf(string, "<NULL>");
10927  else
10928  switch (type) {
10929  case TID_UINT8:
10930  sprintf(string, format, *(((BYTE *) data) + idx));
10931  break;
10932  case TID_INT8:
10933  sprintf(string, format, *(((char *) data) + idx));
10934  break;
10935  case TID_CHAR:
10936  sprintf(string, format, *(((char *) data) + idx));
10937  break;
10938  case TID_UINT16:
10939  sprintf(string, format, *(((WORD *) data) + idx));
10940  break;
10941  case TID_INT16:
10942  sprintf(string, format, *(((short *) data) + idx));
10943  break;
10944  case TID_UINT32:
10945  sprintf(string, format, *(((DWORD *) data) + idx));
10946  break;
10947  case TID_INT32:
10948  sprintf(string, format, *(((INT *) data) + idx));
10949  break;
10950  case TID_UINT64:
10951  sprintf(string, format, *(((UINT64 *) data) + idx));
10952  break;
10953  case TID_INT64:
10954  sprintf(string, format, *(((INT64 *) data) + idx));
10955  break;
10956  case TID_BOOL:
10957  sprintf(string, format, *(((BOOL *) data) + idx) ? 'y' : 'n');
10958  break;
10959  case TID_FLOAT:
10960  if (ss_isnan(*(((float *) data) + idx)))
10961  sprintf(string, "NAN");
10962  else
10963  sprintf(string, format, *(((float *) data) + idx));
10964  break;
10965  case TID_DOUBLE:
10966  if (ss_isnan(*(((double *) data) + idx)))
10967  sprintf(string, "NAN");
10968  else
10969  sprintf(string, format, *(((double *) data) + idx));
10970  break;
10971  case TID_BITFIELD:
10972  sprintf(string, format, *(((DWORD *) data) + idx));
10973  break;
10974  case TID_STRING:
10975  case TID_LINK:
10976  strlcpy(string, ((char *) data) + data_size * idx, MAX_STRING_LENGTH);
10977  break;
10978  default:
10979  sprintf(string, "<unknown>");
10980  break;
10981  }
10982 
10983  return DB_SUCCESS;
10984 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_sprintff() [2/2]

std::string EXPRT db_sprintff ( const char *  format,
const void *  data,
INT  data_size,
INT  idx,
DWORD  type 
)

Same as db_sprintf, but with additional format parameter

Parameters
stringoutput ASCII string of data.
formatFormat specifier passed to sprintf()
dataValue data.
data_sizeSize of single data element.
idxIndex for array data.
typeType of key, one of TID_xxx (see Midas_Data_Types).
Returns
DB_SUCCESS

Definition at line 11167 of file odb.cxx.

11168 {
11169  if (data_size == 0) {
11170  return "<NULL>";
11171  } else {
11172  char buf[256];
11173  switch (type) {
11174  case TID_UINT8:
11175  sprintf(buf, format, *(((BYTE *) data) + idx));
11176  return buf;
11177  case TID_INT8:
11178  sprintf(buf, format, *(((char *) data) + idx));
11179  return buf;
11180  case TID_CHAR:
11181  sprintf(buf, format, *(((char *) data) + idx));
11182  return buf;
11183  case TID_UINT16:
11184  sprintf(buf, format, *(((WORD *) data) + idx));
11185  return buf;
11186  case TID_INT16:
11187  sprintf(buf, format, *(((short *) data) + idx));
11188  return buf;
11189  case TID_UINT32:
11190  sprintf(buf, format, *(((DWORD *) data) + idx));
11191  return buf;
11192  case TID_INT32:
11193  sprintf(buf, format, *(((INT *) data) + idx));
11194  return buf;
11195  case TID_UINT64:
11196  sprintf(buf, format, *(((UINT64 *) data) + idx));
11197  return buf;
11198  case TID_INT64:
11199  sprintf(buf, format, *(((INT64 *) data) + idx));
11200  return buf;
11201  case TID_BOOL:
11202  sprintf(buf, format, *(((BOOL *) data) + idx) ? 'y' : 'n');
11203  return buf;
11204  case TID_FLOAT:
11205  if (ss_isnan(*(((float *) data) + idx))) {
11206  return "NAN";
11207  } else {
11208  sprintf(buf, format, *(((float *) data) + idx));
11209  return buf;
11210  }
11211  case TID_DOUBLE:
11212  if (ss_isnan(*(((double *) data) + idx))) {
11213  return "NAN";
11214  } else {
11215  sprintf(buf, format, *(((double *) data) + idx));
11216  return buf;
11217  }
11218  case TID_BITFIELD:
11219  sprintf(buf, format, *(((DWORD *) data) + idx));
11220  return buf;
11221  case TID_STRING:
11222  case TID_LINK:
11223  return (((char *) data) + data_size * idx);
11224  default:
11225  return "<unknown>";
11226  }
11227  }
11228 }
Here is the call graph for this function:

◆ db_sprintfh() [1/2]

INT EXPRT db_sprintfh ( char *  string,
const void *  data,
INT  data_size,
INT  idx,
DWORD  type 
)

Definition at line 10987 of file odb.cxx.

11008 {
11009  if (data_size == 0)
11010  sprintf(string, "<NULL>");
11011  else
11012  switch (type) {
11013  case TID_UINT8:
11014  sprintf(string, "0x%X", *(((BYTE *) data) + idx));
11015  break;
11016  case TID_INT8:
11017  sprintf(string, "0x%X", *(((char *) data) + idx));
11018  break;
11019  case TID_CHAR:
11020  sprintf(string, "%c", *(((char *) data) + idx));
11021  break;
11022  case TID_UINT16:
11023  sprintf(string, "0x%X", *(((WORD *) data) + idx));
11024  break;
11025  case TID_INT16:
11026  sprintf(string, "0x%hX", *(((short *) data) + idx));
11027  break;
11028  case TID_UINT32:
11029  sprintf(string, "0x%X", *(((DWORD *) data) + idx));
11030  break;
11031  case TID_INT32:
11032  sprintf(string, "0x%X", *(((INT *) data) + idx));
11033  break;
11034  case TID_UINT64:
11035  sprintf(string, "0x%llX", *(((UINT64 *) data) + idx));
11036  break;
11037  case TID_INT64:
11038  sprintf(string, "0x%llX", *(((INT64 *) data) + idx));
11039  break;
11040  case TID_BOOL:
11041  sprintf(string, "%c", *(((BOOL *) data) + idx) ? 'y' : 'n');
11042  break;
11043  case TID_FLOAT:
11044  if (ss_isnan(*(((float *) data) + idx)))
11045  sprintf(string, "NAN");
11046  else
11047  sprintf(string, "%.7g", *(((float *) data) + idx));
11048  break;
11049  case TID_DOUBLE:
11050  if (ss_isnan(*(((double *) data) + idx)))
11051  sprintf(string, "NAN");
11052  else
11053  sprintf(string, "%.16lg", *(((double *) data) + idx));
11054  break;
11055  case TID_BITFIELD:
11056  sprintf(string, "0x%X", *(((DWORD *) data) + idx));
11057  break;
11058  case TID_STRING:
11059  case TID_LINK:
11060  sprintf(string, "%s", ((char *) data) + data_size * idx);
11061  break;
11062  default:
11063  sprintf(string, "<unknown>");
11064  break;
11065  }
11066 
11067  return DB_SUCCESS;
11068 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_sprintfh() [2/2]

std::string EXPRT db_sprintfh ( const void *  data,
INT  data_size,
INT  idx,
DWORD  type 
)

dox

Definition at line 11234 of file odb.cxx.

11255 {
11256  if (data_size == 0) {
11257  return "<NULL>";
11258  } else {
11259  char buf[256];
11260  switch (type) {
11261  case TID_UINT8:
11262  sprintf(buf, "0x%X", *(((BYTE *) data) + idx));
11263  return buf;
11264  case TID_INT8:
11265  sprintf(buf, "0x%X", *(((char *) data) + idx));
11266  return buf;
11267  case TID_CHAR:
11268  sprintf(buf, "%c", *(((char *) data) + idx));
11269  return buf;
11270  case TID_UINT16:
11271  sprintf(buf, "0x%X", *(((WORD *) data) + idx));
11272  return buf;
11273  case TID_INT16:
11274  sprintf(buf, "0x%hX", *(((short *) data) + idx));
11275  return buf;
11276  case TID_UINT32:
11277  sprintf(buf, "0x%X", *(((DWORD *) data) + idx));
11278  return buf;
11279  case TID_INT32:
11280  sprintf(buf, "0x%X", *(((INT *) data) + idx));
11281  return buf;
11282  case TID_UINT64:
11283  sprintf(buf, "0x%llX", *(((UINT64 *) data) + idx));
11284  return buf;
11285  case TID_INT64:
11286  sprintf(buf, "0x%llX", *(((INT64 *) data) + idx));
11287  return buf;
11288  case TID_BOOL:
11289  sprintf(buf, "%c", *(((BOOL *) data) + idx) ? 'y' : 'n');
11290  return buf;
11291  case TID_FLOAT:
11292  if (ss_isnan(*(((float *) data) + idx))) {
11293  return "NAN";
11294  } else {
11295  sprintf(buf, "%.7g", *(((float *) data) + idx));
11296  return buf;
11297  }
11298  case TID_DOUBLE:
11299  if (ss_isnan(*(((double *) data) + idx))) {
11300  return "NAN";
11301  } else {
11302  sprintf(buf, "%.16lg", *(((double *) data) + idx));
11303  return buf;
11304  }
11305  case TID_BITFIELD:
11306  sprintf(buf, "0x%X", *(((DWORD *) data) + idx));
11307  return buf;
11308  case TID_STRING:
11309  case TID_LINK:
11310  return (((char *) data) + data_size * idx);
11311  default:
11312  return "<unknown>";
11313  }
11314  }
11315 }
Here is the call graph for this function:

◆ db_sscanf()

INT EXPRT db_sscanf ( const char *  data_str,
void *  data,
INT data_size,
INT  i,
DWORD  tid 
)

Definition at line 11318 of file odb.cxx.

11338 {
11339  DWORD value = 0;
11340  BOOL hex = FALSE;
11341 
11342  if (data_str == NULL)
11343  return 0;
11344 
11345  *data_size = rpc_tid_size(tid);
11346  if (strncmp(data_str, "0x", 2) == 0) {
11347  hex = TRUE;
11348  sscanf(data_str + 2, "%x", &value);
11349  }
11350 
11351  switch (tid) {
11352  case TID_UINT8:
11353  case TID_INT8:
11354  if (hex)
11355  *((char *) data + i) = (char) value;
11356  else
11357  *((char *) data + i) = (char) atoi(data_str);
11358  break;
11359  case TID_CHAR:
11360  *((char *) data + i) = data_str[0];
11361  break;
11362  case TID_UINT16:
11363  if (hex)
11364  *((WORD *) data + i) = (WORD) value;
11365  else
11366  *((WORD *) data + i) = (WORD) atoi(data_str);
11367  break;
11368  case TID_INT16:
11369  if (hex)
11370  *((short int *) data + i) = (short int) value;
11371  else
11372  *((short int *) data + i) = (short int) atoi(data_str);
11373  break;
11374  case TID_UINT32:
11375  if (hex)
11376  value = strtoul(data_str, nullptr, 16);
11377  else
11378  value = strtoul(data_str, nullptr, 10);
11379 
11380  *((DWORD *) data + i) = value;
11381  break;
11382  case TID_INT32:
11383  if (hex)
11384  value = strtol(data_str, nullptr, 16);
11385  else
11386  value = strtol(data_str, nullptr, 10);
11387 
11388  *((INT *) data + i) = value;
11389  break;
11390  case TID_UINT64:
11391  if (hex)
11392  *((UINT64 *) data + i) = strtoull(data_str, nullptr, 16);
11393  else
11394  *((UINT64 *) data + i) = strtoull(data_str, nullptr, 10);
11395  break;
11396  case TID_INT64:
11397  if (hex)
11398  *((UINT64 *) data + i) = strtoll(data_str, nullptr, 16);
11399  else
11400  *((UINT64 *) data + i) = strtoll(data_str, nullptr, 10);
11401  break;
11402  case TID_BOOL:
11403  if (data_str[0] == 'y' || data_str[0] == 'Y' ||
11404  data_str[0] == 't' || data_str[0] == 'T' || atoi(data_str) > 0)
11405  *((BOOL *) data + i) = 1;
11406  else
11407  *((BOOL *) data + i) = 0;
11408  break;
11409  case TID_FLOAT:
11410  if (data_str[0] == 'n' || data_str[0] == 'N')
11411  *((float *) data + i) = (float) ss_nan();
11412  else
11413  *((float *) data + i) = (float) atof(data_str);
11414  break;
11415  case TID_DOUBLE:
11416  if (data_str[0] == 'n' || data_str[0] == 'N')
11417  *((double *) data + i) = ss_nan();
11418  else
11419  *((double *) data + i) = atof(data_str);
11420  break;
11421  case TID_BITFIELD:
11422  if (hex)
11423  value = strtoul(data_str, nullptr, 16);
11424  else
11425  value = strtoul(data_str, nullptr, 10);
11426 
11427  *((DWORD *) data + i) = value;
11428  break;
11429  case TID_STRING:
11430  case TID_LINK:
11431  strcpy((char *) data, data_str);
11432  *data_size = strlen(data_str) + 1;
11433  break;
11434  }
11435 
11436  return DB_SUCCESS;
11437 }
double ss_nan()
Definition: system.cxx:7879
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_unlock_database()

INT db_unlock_database ( HNDLE  hDB)

Unlock a database via system semaphore calls.

Parameters
hDBHandle to the database to unlock
Returns
DB_SUCCESS, DB_INVALID_HANDLE

Definition at line 2565 of file odb.cxx.

2566 {
2567 #ifdef LOCAL_ROUTINES
2568 
2569  if (hDB > _database_entries || hDB <= 0) {
2570  cm_msg(MERROR, "db_unlock_database", "invalid database handle %d", hDB);
2571  return DB_INVALID_HANDLE;
2572  }
2573 #ifdef CHECK_LOCK_COUNT
2574  {
2575  char str[256];
2576 
2577  sprintf(str, "db_unlock_database, lock_cnt=%d", _database[hDB - 1].lock_cnt);
2579  }
2580 #endif
2581 
2582  /* protect this function against recursive call from signal handlers */
2583  if (_database[hDB - 1].inside_lock_unlock) {
2584  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");
2585  abort();
2586  }
2587 
2588  _database[hDB - 1].inside_lock_unlock = 1;
2589 
2590  //static int x = 0;
2591  //x++;
2592  //if (x > 5000) {
2593  // printf("inside db_unlock_database(), press Ctrl-C now!\n");
2594  // sleep(5);
2595  //}
2596 
2597  if (_database[hDB - 1].lock_cnt == 1) {
2598  ss_semaphore_release(_database[hDB - 1].semaphore);
2599 
2600  if (_database[hDB - 1].protect && _database[hDB - 1].database_header) {
2601  int status;
2602  assert(_database[hDB - 1].protect_read);
2603  assert(_database[hDB - 1].database_header);
2604  _database[hDB - 1].database_header = NULL;
2605  status = ss_shm_protect(_database[hDB - 1].shm_handle, _database[hDB - 1].shm_adr, _database[hDB - 1].shm_size);
2606  if (status != SS_SUCCESS) {
2607  cm_msg(MERROR, "db_unlock_database", "cannot unlock ODB, ss_shm_protect() failed with status %d, aborting...", status);
2609  abort();
2610  }
2613  }
2614  }
2615 
2616  assert(_database[hDB - 1].lock_cnt > 0);
2617  _database[hDB - 1].lock_cnt--;
2618 
2619  _database[hDB - 1].inside_lock_unlock = 0;
2620 
2621  /* release mutex for multi-thread applications */
2622  ss_mutex_release(_database[hDB - 1].mutex);
2623 
2624 #endif /* LOCAL_ROUTINES */
2625  return DB_SUCCESS;
2626 }
INT ss_mutex_release(MUTEX_T *mutex)
Definition: system.cxx:3096
INT ss_semaphore_release(HNDLE semaphore_handle)
Definition: system.cxx:2720
Here is the call graph for this function:

◆ db_unwatch()

INT EXPRT db_unwatch ( HNDLE  hDB,
HNDLE  hKey 
)

Remove watch callback from a key previously watched with db_watch.

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key, zero for root.
Returns
DB_SUCCESS, DB_INVALID_HANDLE

Definition at line 13890 of file odb.cxx.

13891 {
13892 #ifdef LOCAL_ROUTINES
13893  {
13894  INT i;
13895 
13896  for (i = 0; i < _watch_list_entries; i++)
13897  if (_watch_list[i].handle == hKey && _watch_list[i].hDB == hDB)
13898  break;
13899 
13900  if (i == _watch_list_entries)
13901  return DB_INVALID_HANDLE;
13902 
13903  /* remove record entry from database structure */
13905 
13906  memset(&_watch_list[i], 0, sizeof(WATCH_LIST));
13907  }
13908 #endif /* LOCAL_ROUTINES */
13909 
13910  return DB_SUCCESS;
13911 }
static WATCH_LIST * _watch_list
Definition: odb.cxx:64
static INT _watch_list_entries
Definition: odb.cxx:65
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_unwatch_all()

INT EXPRT db_unwatch_all ( )

Closes all watched variables. This routines is called by db_close_all_databases() and cm_disconnect_experiment()

Returns
DB_SUCCESS, DB_INVALID_HANDLE

Definition at line 13920 of file odb.cxx.

13921 {
13922  for (int i = _watch_list_entries-1; i >= 0 ; i--) {
13923  if ((_watch_list[i].hDB == 0) && (_watch_list[i].handle == 0)) {
13924  // empty or deleted watch list entry
13925  continue;
13926  }
13927  db_unwatch(_watch_list[i].hDB, _watch_list[i].handle);
13928  }
13929 
13930  return DB_SUCCESS;
13931 }
INT db_unwatch(HNDLE hDB, HNDLE hKey)
Definition: odb.cxx:13890
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_update_last_activity()

INT EXPRT db_update_last_activity ( DWORD  millitime)

Update last activity time

Definition at line 2682 of file odb.cxx.

2683 {
2684  bool found = false;
2685  int pid = ss_getpid();
2686  for (int i = 0; i < _database_entries; i++) {
2687  if (_database[i].attached) {
2688  db_lock_database(i + 1);
2689  db_allow_write_locked(&_database[i], "db_update_last_activity");
2690  assert(_database[i].database_header);
2691  /* update the last_activity entry to show that we are alive */
2692  for (int j=0; j<_database[i].database_header->max_client_index; j++) {
2694  //printf("client %d pid %d vs our pid %d\n", j, pdbclient->pid, pid);
2695  if (pdbclient->pid == pid) {
2696  pdbclient->last_activity = millitime;
2697  found = true;
2698  }
2699  }
2700  db_unlock_database(i + 1);
2701  }
2702  }
2703 
2704  if (!found) {
2705  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...");
2706  abort();
2707  }
2708 
2709  return DB_SUCCESS;
2710 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_update_open_record_wlocked()

static int db_update_open_record_wlocked ( const DATABASE_HEADER xpheader,
const KEY xpkey,
int  level,
void *  voidp,
db_err_msg **  msg 
)
static

Definition at line 1510 of file odb.cxx.

1511 {
1512  int found = 0;
1513  int count = 0;
1514  int status;
1515  int k;
1516  UPDATE_OPEN_RECORDS *uorp = (UPDATE_OPEN_RECORDS *)voidp;
1517 
1518  KEY* pkey = (KEY*)xpkey; // drop "const": we already have "allow_write"
1519 
1520  HNDLE hKey = db_pkey_to_hkey(uorp->pheader, pkey);
1521 
1522  for (k=0; k<uorp->num_keys; k++)
1523  if (uorp->hkeys[k] == hKey) {
1524  found = 1;
1525  count = uorp->counts[k];
1526  break;
1527  }
1528 
1529  if (pkey->notify_count == 0 && !found)
1530  return DB_SUCCESS; // no open record here
1531 
1532  std::string path = db_get_path_locked(uorp->pheader, hKey);
1533  if (path == "") {
1534  db_msg(msg, MINFO, "db_update_open_record", "Invalid hKey %d", hKey);
1535  return DB_SUCCESS;
1536  }
1537 
1538  //if (!db_validate_hkey(uorp->pheader, hKey)) {
1539  // cm_msg(MINFO, "db_update_open_record", "Invalid hKey %d", hKey);
1540  // return DB_SUCCESS;
1541  //}
1542  //
1543  //KEY* pkey = (KEY *) ((char *) uorp->pheader + hKey);
1544 
1545  //printf("path [%s], type %d, notify_count %d\n", path, pkey->type, pkey->notify_count);
1546 
1547  // extra check: are we looking at the same key?
1548  //assert(xkey->notify_count == pkey->notify_count);
1549 
1550 #if 0
1551  printf("%s, notify_count %d, found %d, our count %d\n", path, pkey->notify_count, found, count);
1552 #endif
1553 
1554  if (pkey->notify_count==0 && found) {
1555  db_msg(msg, MINFO, "db_update_open_record", "Added missing open record flag to \"%s\"", path.c_str());
1556  pkey->notify_count = count;
1557  uorp->num_modified++;
1558  return DB_SUCCESS;
1559  }
1560 
1561  if (pkey->notify_count!=0 && !found) {
1562  db_msg(msg, MINFO, "db_update_open_record", "Removed open record flag from \"%s\"", path.c_str());
1563  pkey->notify_count = 0;
1564  uorp->num_modified++;
1565 
1566  if (pkey->access_mode | MODE_EXCLUSIVE) {
1567  status = db_set_mode_wlocked(uorp->pheader, pkey, (WORD) (pkey->access_mode & ~MODE_EXCLUSIVE), 1, msg);
1568  if (status != DB_SUCCESS) {
1569  db_msg(msg, MERROR, "db_update_open_record", "Cannot remove exclusive access mode from \"%s\", db_set_mode() status %d", path.c_str(), status);
1570  return DB_SUCCESS;
1571  }
1572  db_msg(msg, MINFO, "db_update_open_record", "Removed exclusive access mode from \"%s\"", path.c_str());
1573  }
1574  return DB_SUCCESS;
1575  }
1576 
1577  if (pkey->notify_count != uorp->counts[k]) {
1578  db_msg(msg, MINFO, "db_update_open_record", "Updated notify_count of \"%s\" from %d to %d", path.c_str(), pkey->notify_count, count);
1579  pkey->notify_count = count;
1580  uorp->num_modified++;
1581  return DB_SUCCESS;
1582  }
1583 
1584  return DB_SUCCESS;
1585 }
DATABASE_HEADER * pheader
Definition: odb.cxx:1501
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_update_record_local()

INT db_update_record_local ( INT  hDB,
INT  hKeyRoot,
INT  hKey,
int  index 
)

db_open_record() and db_watch() event handler

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key which changed.
indexIndex for array keys.
Returns
DB_SUCCESS, DB_INVALID_HANDLE

Definition at line 13556 of file odb.cxx.

13557 {
13558  INT i, size, status;
13559 
13561 
13562  /* check all record entries for matching key */
13563  for (i = 0; i < _record_list_entries; i++)
13564  if (_record_list[i].handle == hKeyRoot) {
13565  status = DB_SUCCESS;
13566 
13567  /* get updated data if record not opened in write mode */
13568  if ((_record_list[i].access_mode & MODE_WRITE) == 0) {
13569  size = _record_list[i].buf_size;
13570  if (_record_list[i].data != NULL) {
13571  status = db_get_record(hDB, hKeyRoot, _record_list[i].data, &size, 0); // db_open_record() update
13572  //printf("db_open_record update status %d, size %d %d\n", status, _record_list[i].buf_size, size);
13573  }
13574 
13575  /* call dispatcher if requested */
13576  if (_record_list[i].dispatcher)
13577  _record_list[i].dispatcher(hDB, hKeyRoot, _record_list[i].info);
13578  }
13579  }
13580 
13581  /* check all watch entries for matching key */
13582  for (i = 0; i < _watch_list_entries; i++)
13583  if (_watch_list[i].handle == hKeyRoot) {
13584  status = DB_SUCCESS;
13585 
13586  /* call dispatcher if requested */
13587  if (_watch_list[i].dispatcher)
13589  }
13590 
13591  return status;
13592 }
void(* dispatcher)(INT, INT, INT, void *info)
Definition: msystem.h:481
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_update_record_mserver()

INT db_update_record_mserver ( INT  hDB,
INT  hKeyRoot,
INT  hKey,
int  index,
int  client_socket 
)

Relay db_open_record() and db_watch() notification to the remote client.

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key which changed.
indexIndex for array keys.
sclient socket.
Returns
DB_SUCCESS, DB_INVALID_HANDLE

Definition at line 13603 of file odb.cxx.

13604 {
13605  char buffer[32];
13606 
13607  int convert_flags = rpc_get_convert_flags();
13608 
13609  NET_COMMAND* nc = (NET_COMMAND *) buffer;
13610 
13611  nc->header.routine_id = MSG_ODB;
13612  nc->header.param_size = 4 * sizeof(INT);
13613  *((INT *) nc->param) = hDB;
13614  *((INT *) nc->param + 1) = hKeyRoot;
13615  *((INT *) nc->param + 2) = hKey;
13616  *((INT *) nc->param + 3) = index;
13617 
13618  if (convert_flags) {
13621  rpc_convert_single(&nc->param[0], TID_UINT32, RPC_OUTGOING, convert_flags);
13622  rpc_convert_single(&nc->param[4], TID_UINT32, RPC_OUTGOING, convert_flags);
13623  rpc_convert_single(&nc->param[8], TID_UINT32, RPC_OUTGOING, convert_flags);
13624  rpc_convert_single(&nc->param[12], TID_UINT32, RPC_OUTGOING, convert_flags);
13625  }
13626 
13627  /* send the update notification to the client */
13628  send_tcp(client_socket, buffer, sizeof(NET_COMMAND_HEADER) + 4 * sizeof(INT), 0);
13629 
13630  return DB_SUCCESS;
13631 }
#define MSG_ODB
Definition: msystem.h:296
INT send_tcp(int sock, char *buffer, DWORD buffer_size, INT flags)
Definition: system.cxx:5218
NET_COMMAND_HEADER header
Definition: msystem.h:286
char param[32]
Definition: msystem.h:287
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_validate_and_repair_db_wlocked()

static bool db_validate_and_repair_db_wlocked ( DATABASE_HEADER pheader,
db_err_msg **  msg 
)
static

Definition at line 1650 of file odb.cxx.

1651 {
1652  int total_size_key = 0;
1653  int total_size_data = 0;
1654  double ratio;
1655  FREE_DESCRIP *pfree;
1656  bool flag = true;
1657 
1658  /* validate size of data structures (miscompiled, 32/64 bit mismatch, etc */
1659 
1661 
1662  /* validate the key free list */
1663 
1664  if (!db_validate_key_offset(pheader, pheader->first_free_key)) {
1665  db_msg(msg, MERROR, "db_validate_db", "Error: database corruption, invalid pheader->first_free_key 0x%08X", pheader->first_free_key - (int)sizeof(DATABASE_HEADER));
1666  return false;
1667  }
1668 
1669  pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_key);
1670 
1671  while ((POINTER_T) pfree != (POINTER_T) pheader) {
1672 
1673  if (pfree->next_free != 0 && !db_validate_key_offset(pheader, pfree->next_free)) {
1674  db_msg(msg, MERROR, "db_validate_db", "Warning: database corruption, invalid key area next_free 0x%08X", pfree->next_free - (int)sizeof(DATABASE_HEADER));
1675  flag = false;
1676  break;
1677  }
1678 
1679  total_size_key += pfree->size;
1680  FREE_DESCRIP *nextpfree = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
1681 
1682  if (pfree->next_free != 0 && nextpfree == pfree) {
1683  db_msg(msg, MERROR, "db_validate_db", "Warning: database corruption, key area next_free 0x%08X is same as current free %p, truncating the free list", pfree->next_free, pfree - (int)sizeof(DATABASE_HEADER));
1684  pfree->next_free = 0;
1685  flag = false;
1686  break;
1687  //return false;
1688  }
1689 
1690  pfree = nextpfree;
1691  }
1692 
1693  ratio = ((double) (pheader->key_size - total_size_key)) / ((double) pheader->key_size);
1694  if (ratio > 0.9)
1695  db_msg(msg, MERROR, "db_validate_db", "Warning: database key area is %.0f%% full", ratio * 100.0);
1696 
1697  if (total_size_key > pheader->key_size) {
1698  db_msg(msg, MERROR, "db_validate_db", "Error: database corruption, total_key_size 0x%08X bigger than pheader->key_size 0x%08X", total_size_key, pheader->key_size);
1699  flag = false;
1700  }
1701 
1702  /* validate the data free list */
1703 
1704  if (!db_validate_data_offset(pheader, pheader->first_free_data)) {
1705  db_msg(msg, MERROR, "db_validate_db", "Error: database corruption, invalid pheader->first_free_data 0x%08X", pheader->first_free_data - (int)sizeof(DATABASE_HEADER));
1706  return false;
1707  }
1708 
1709  //printf("pheader %p, first_free_data %d, key size %d, data size %d\n", pheader, pheader->first_free_data, pheader->key_size, pheader->data_size);
1710 
1711  pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_data);
1712 
1713  while ((POINTER_T) pfree != (POINTER_T) pheader) {
1714 
1715  if (pfree->next_free != 0 && !db_validate_data_offset(pheader, pfree->next_free)) {
1716  db_msg(msg, MERROR, "db_validate_db", "Warning: database corruption, invalid data area next_free 0x%08X", pfree->next_free - (int)sizeof(DATABASE_HEADER));
1717  flag = false;
1718  break;
1719  //return false;
1720  }
1721 
1722  total_size_data += pfree->size;
1723  FREE_DESCRIP *nextpfree = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
1724 
1725  if (pfree->next_free != 0 && nextpfree == pfree) {
1726  db_msg(msg, MERROR, "db_validate_db", "Warning: database corruption, data area next_free 0x%08X is same as current free %p, truncating the free list", pfree->next_free, pfree - (int)sizeof(DATABASE_HEADER));
1727  pfree->next_free = 0;
1728  flag = false;
1729  break;
1730  //return false;
1731  }
1732 
1733  pfree = nextpfree;
1734  }
1735 
1736  ratio = ((double) (pheader->data_size - total_size_data)) / ((double) pheader->data_size);
1737  if (ratio > 0.9)
1738  db_msg(msg, MERROR, "db_validate_db", "Warning: database data area is %.0f%% full", ratio * 100.0);
1739 
1740  if (total_size_data > pheader->data_size) {
1741  db_msg(msg, MERROR, "db_validate_db", "Error: database corruption, total_size_data 0x%08X bigger than pheader->data_size 0x%08X", total_size_key, pheader->data_size);
1742  flag = false;
1743  //return false;
1744  }
1745 
1746  /* validate the tree of keys, starting from the root key */
1747 
1748  if (!db_validate_key_offset(pheader, pheader->root_key)) {
1749  db_msg(msg, MERROR, "db_validate_db", "Error: database corruption, pheader->root_key 0x%08X is invalid", pheader->root_key - (int)sizeof(DATABASE_HEADER));
1750  return false;
1751  }
1752 
1753  flag &= db_validate_and_repair_key_wlocked(pheader, 1, "", 0, pheader->root_key, (KEY *) ((char *) pheader + pheader->root_key), msg);
1754 
1755  if (!flag) {
1756  db_msg(msg, MERROR, "db_validate_db", "Error: ODB corruption detected, see previous messages");
1757  }
1758 
1759  return flag;
1760 }
static void db_validate_sizes()
Definition: odb.cxx:1402
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_validate_and_repair_key_wlocked()

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 
)
static

Definition at line 1148 of file odb.cxx.

1149 {
1150  int status;
1151  bool flag = true;
1152 
1153  //printf("path \"%s\", parenthkey %d, hkey %d, pkey->name \"%s\", type %d\n", path, parenthkeylist, hkey, pkey->name, pkey->type);
1154 
1155  //std::string xpath = db_get_path_locked(pheader, hkey);
1156  //if (xpath != path)
1157  // printf("hkey %d, path \"%s\" vs \"%s\"\n", hkey, path, xpath.c_str());
1158 
1159  //db_print_key(pheader, 0, path, parenthkeylist, hkey);
1160 
1161  if (hkey==0 || !db_validate_key_offset(pheader, hkey)) {
1162  db_msg(msg, MERROR, "db_validate_key", "hkey %d, path \"%s\", invalid hkey", hkey, path);
1163  return false;
1164  }
1165 
1166  /* check key type */
1167  if (pkey->type <= 0 || pkey->type >= TID_LAST) {
1168  db_msg(msg, MERROR, "db_validate_key", "hkey %d, path \"%s\", name \"%s\", invalid key type %d", hkey, path, pkey->name, pkey->type);
1169  return false;
1170  }
1171 
1172  /* check key name */
1173  status = db_validate_name(pkey->name, FALSE, "db_validate_key", msg);
1174  if (status != DB_SUCCESS) {
1175  char newname[NAME_LENGTH];
1176  sprintf(newname, "%p", pkey);
1177  db_msg(msg, MERROR, "db_validate_key", "hkey %d, path \"%s\": invalid name \"%s\" replaced with \"%s\"", hkey, path, pkey->name, newname);
1178  strlcpy(pkey->name, newname, sizeof(pkey->name));
1179  flag = false;
1180  //return false;
1181  }
1182 
1183  /* check parent */
1184  if (pkey->parent_keylist != parenthkeylist) {
1185  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);
1186  return false;
1187  }
1188 
1189  if (!db_validate_data_offset(pheader, pkey->data)) {
1190  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));
1191  return false;
1192  }
1193 
1194  /* check key sizes */
1195  if ((pkey->total_size < 0) || (pkey->total_size > pheader->data_size)) {
1196  db_msg(msg, MERROR, "db_validate_key", "hkey %d, path \"%s\", invalid pkey->total_size %d", hkey, path, pkey->total_size);
1197  return false;
1198  }
1199 
1200  if ((pkey->item_size < 0) || (pkey->item_size > pheader->data_size)) {
1201  db_msg(msg, MERROR, "db_validate_key", "hkey %d, path \"%s\", invalid pkey->item_size: %d", hkey, path, pkey->item_size);
1202  return false;
1203  }
1204 
1205  if ((pkey->num_values < 0) || (pkey->num_values > pheader->data_size)) {
1206  db_msg(msg, MERROR, "db_validate_key", "hkey %d, path \"%s\", invalid pkey->num_values: %d", hkey, path, pkey->num_values);
1207  return false;
1208  }
1209 
1210  /* check and correct key size */
1211  if (pkey->total_size != pkey->item_size * pkey->num_values) {
1212  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);
1213  pkey->total_size = pkey->item_size * pkey->num_values;
1214  flag = false;
1215  }
1216 
1217  /* check and correct key size */
1218  if (pkey->data == 0 && pkey->total_size != 0) {
1219  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);
1220  pkey->num_values = 0;
1221  pkey->total_size = 0;
1222  flag = false;
1223  }
1224 
1225  if (pkey->type == TID_STRING || pkey->type == TID_LINK) {
1226  const char* s = (char*)pheader + pkey->data;
1227  if (!is_utf8(s)) {
1228  db_msg(msg, MERROR, "db_validate_key", "hkey %d, path \"%s\", string value is not valid UTF-8", hkey, path);
1229  //flag = false;
1230  }
1231  }
1232 
1233  /* check for empty link */
1234  if (pkey->type == TID_LINK) {
1235  // minimum symlink length is 3 bytes:
1236  // one byte "/"
1237  // one byte odb entry name
1238  // one byte "\0"
1239  if (pkey->total_size <= 2) {
1240  db_msg(msg, MERROR, "db_validate_key", "hkey %d, path \"%s\", TID_LINK is an empty link", hkey, path);
1241  flag = false;
1242  //return false;
1243  }
1244  }
1245 
1246  /* check for too long link */
1247  if (pkey->type == TID_LINK) {
1248  if (pkey->total_size >= MAX_ODB_PATH) {
1249  db_msg(msg, MERROR, "db_validate_key", "hkey %d, path \"%s\", TID_LINK length %d exceeds MAX_ODB_PATH %d", hkey, path, pkey->total_size, MAX_ODB_PATH);
1250  flag = false;
1251  //return false;
1252  }
1253  }
1254 
1255  /* check for link loop */
1256  if (pkey->type == TID_LINK) {
1257  const char* link = (char*)pheader + pkey->data;
1258  int link_len = strlen(link);
1259  int path_len = strlen(path);
1260  if (link_len == path_len) {
1261  // check for link to itself
1262  if (equal_ustring(link, path)) {
1263  db_msg(msg, MERROR, "db_validate_key", "hkey %d, path \"%s\", TID_LINK to \"%s\" is a link to itself", hkey, path, link);
1264  flag = false;
1265  //return false;
1266  }
1267  } else if (link_len < path_len) {
1268  // check for link to the "path" subdirectory
1269  char tmp[MAX_ODB_PATH];
1270  memcpy(tmp, path, link_len);
1271  tmp[link_len] = 0;
1272  if (equal_ustring(link, tmp) && path[link_len] == DIR_SEPARATOR) {
1273  db_msg(msg, MERROR, "db_validate_key", "hkey %d, path \"%s\", TID_LINK to \"%s\" is a loop", hkey, path, link);
1274  flag = false;
1275  //return false;
1276  }
1277  }
1278  }
1279 
1280  /* check access mode */
1282  db_msg(msg, MERROR, "db_validate_key", "hkey %d, path \"%s\", invalid pkey->access_mode %d", hkey, path, pkey->access_mode);
1283  flag = false;
1284  //return false;
1285  }
1286 
1287  /* check if access time is in the future */
1288  if (pkey->last_written > 0 && ((DWORD)pkey->last_written > ss_time() + 3600)) {
1289  db_msg(msg, MERROR, "db_validate_key", "hkey %d, path \"%s\", invalid pkey->last_written time %d", hkey, path, pkey->last_written);
1290  flag = false;
1291  //return false;
1292  }
1293 
1294  if (pkey->type == TID_KEY) {
1295  bool pkeylist_ok = true;
1296  // FIXME: notice the kludged repair of pkeylist! K.O.
1297  const KEYLIST *pkeylist = db_get_pkeylist(pheader, hkey, pkey, "db_validate_key", msg, true);
1298 
1299  if (!pkeylist) {
1300  db_msg(msg, MERROR, "db_validate_key", "hkey %d, path \"%s\", invalid pkey->data %d", hkey, path, pkey->data);
1301  flag = false;
1302  } else {
1303  if (pkeylist->parent != hkey) {
1304  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);
1305  flag = false;
1306  pkeylist_ok = false;
1307  }
1308 
1309  if (pkeylist->num_keys < 0 || pkeylist->num_keys > pheader->key_size) {
1310  db_msg(msg, MERROR, "db_validate_key", "hkey %d, path \"%s\", TID_KEY invalid pkeylist->num_keys %d", hkey, path, pkeylist->num_keys);
1311  flag = false;
1312  pkeylist_ok = false;
1313  }
1314 
1315  if (pkeylist->num_keys == 0 && pkeylist->first_key == 0) {
1316  // empty key
1317  } else if (pkeylist->first_key == 0 || !db_validate_key_offset(pheader, pkeylist->first_key)) {
1318  db_msg(msg, MERROR, "db_validate_key", "hkey %d, path \"%s\", TID_KEY invalid pkeylist->first_key %d", hkey, path, pkeylist->first_key);
1319  flag = false;
1320  pkeylist_ok = false;
1321  }
1322 
1323  if (pkeylist_ok) {
1324  //printf("hkey %d, path \"%s\", pkey->data %d, pkeylist parent %d, num_keys %d, first_key %d: ", hkey, path, pkey->data, pkeylist->parent, pkeylist->num_keys, pkeylist->first_key);
1325 
1326  HNDLE subhkey = pkeylist->first_key;
1327 
1328  int count = 0;
1329  while (subhkey != 0) {
1330  KEY* subpkey = (KEY*)db_get_pkey(pheader, subhkey, NULL, "db_validate_key", msg);
1331  if (!subpkey) {
1332  db_msg(msg, MERROR, "db_validate_key", "hkey %d, path \"%s\", TID_KEY invalid subhkey %d", hkey, path, subhkey);
1333  pkeylist_ok = false;
1334  flag = false;
1335  break;
1336  }
1337 
1338  std::string buf;
1339  buf += path;
1340  buf += "/";
1341  buf += subpkey->name;
1342 
1343  //printf("pkey %p, next %d, name [%s], path %s\n", subpkey, subpkey->next_key, subpkey->name, buf.c_str());
1344 
1345  if (recurse) {
1346  flag &= db_validate_and_repair_key_wlocked(pheader, recurse + 1, buf.c_str(), pkey->data, subhkey, subpkey, msg);
1347  }
1348 
1349  count++;
1350  subhkey = subpkey->next_key;
1351  }
1352 
1353  if (count != pkeylist->num_keys) {
1354  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);
1355  ((KEYLIST*)pkeylist)->num_keys = count;
1356  flag = false;
1357  pkeylist_ok = false;
1358  }
1359  }
1360  }
1361  }
1362 
1363  return flag;
1364 }
#define DIR_SEPARATOR
Definition: midas.h:193
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_validate_data_offset()

static bool db_validate_data_offset ( const DATABASE_HEADER pheader,
int  offset 
)
static

Definition at line 908 of file odb.cxx.

910 {
911  if (offset != 0 && offset < (int) sizeof(DATABASE_HEADER))
912  return false;
913 
914  if (offset > (int) sizeof(DATABASE_HEADER) + pheader->key_size + pheader->data_size)
915  return false;
916 
917  return true;
918 }
Here is the caller graph for this function:

◆ db_validate_hkey()

static bool db_validate_hkey ( const DATABASE_HEADER pheader,
HNDLE  hKey 
)
static

Definition at line 920 of file odb.cxx.

921 {
922  if (hKey == 0) {
923  cm_msg(MERROR, "db_validate_hkey", "Error: invalid zero hkey %d", hKey);
924  return false;
925  }
926  if (!db_validate_key_offset(pheader, hKey)) {
927  cm_msg(MERROR, "db_validate_hkey", "Error: invalid hkey %d", hKey);
928  return false;
929  }
930  return true;
931 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_validate_key_offset()

static bool db_validate_key_offset ( const DATABASE_HEADER pheader,
int  offset 
)
static

Definition at line 896 of file odb.cxx.

898 {
899  if (offset != 0 && offset < (int) sizeof(DATABASE_HEADER))
900  return false;
901 
902  if (offset > (int) sizeof(DATABASE_HEADER) + pheader->key_size)
903  return false;
904 
905  return true;
906 }
Here is the caller graph for this function:

◆ db_validate_name()

static int db_validate_name ( const char *  name,
int  maybe_path,
const char *  caller_name,
db_err_msg **  msg 
)
static

Definition at line 836 of file odb.cxx.

837 {
838  //printf("db_validate_name [%s] length %d, maybe_path %d from %s\n", name, (int)strlen(name), maybe_path, caller_name);
839 
840  if (name == NULL) {
841  db_msg(msg, MERROR, "db_validate_name", "Invalid name passed to %s: should not be NULL", caller_name);
842  return DB_INVALID_NAME;
843  }
844 
845  size_t len = strlen(name);
846 
847  if (len < 1) {
848  db_msg(msg, MERROR, "db_validate_name", "Invalid name passed to %s: should not be an empty string", caller_name);
849  return DB_INVALID_NAME;
850  }
851 
852  if (strchr(name, '[')) {
853  db_msg(msg, MERROR, "db_validate_name", "Invalid name \"%s\" passed to %s: should not contain \"[\"", name, caller_name);
854  return DB_INVALID_NAME;
855  }
856 
857  if (name[0] == ' ') {
858  db_msg(msg, MERROR, "db_validate_name", "Invalid name \"%s\" passed to %s: should not start with a space", name, caller_name);
859  return DB_INVALID_NAME;
860  }
861 
862  if (name[len-1] == ' ') {
863  db_msg(msg, MERROR, "db_validate_name", "Invalid name \"%s\" passed to %s: should not end with a space", name, caller_name);
864  return DB_INVALID_NAME;
865  }
866 
867  if (strchr(name, ']')) {
868  db_msg(msg, MERROR, "db_validate_name", "Invalid name \"%s\" passed to %s: should not contain \"[\"", name, caller_name);
869  return DB_INVALID_NAME;
870  }
871 
872  if (!is_utf8(name)) {
873  db_msg(msg, MERROR, "db_validate_name", "Invalid name \"%s\" passed to %s: invalid unicode UTF-8 encoding", name, caller_name);
874  return DB_INVALID_NAME;
875  }
876 
877  if (!maybe_path) {
878  if (strchr(name, '/')) {
879  db_msg(msg, MERROR, "db_validate_name", "Invalid name \"%s\" passed to %s: should not contain \"/\"", name, caller_name);
880  return DB_INVALID_NAME;
881  }
882 
883  if (strlen(name) >= NAME_LENGTH) {
884  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);
885  return DB_INVALID_NAME;
886  }
887  }
888 
889  //if (strcmp(name, "test")==0)
890  //return DB_INVALID_NAME;
891 
892  return DB_SUCCESS;
893 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_validate_open_records_wlocked()

static int db_validate_open_records_wlocked ( DATABASE_HEADER pheader,
db_err_msg **  msg 
)
static

Definition at line 1587 of file odb.cxx.

1588 {
1589  int status = DB_SUCCESS;
1590  UPDATE_OPEN_RECORDS uor;
1591  int i, j, k;
1592 
1594  uor.num_keys = 0;
1595  uor.hkeys = (HNDLE*)calloc(uor.max_keys, sizeof(HNDLE));
1596  uor.counts = (int*)calloc(uor.max_keys, sizeof(int));
1597  uor.modes = (int*)calloc(uor.max_keys, sizeof(int));
1598  uor.num_modified = 0;
1599 
1600  assert(uor.hkeys != NULL);
1601  assert(uor.counts != NULL);
1602  assert(uor.modes != NULL);
1603 
1604  uor.pheader = pheader;
1605 
1606  for (i = 0; i < pheader->max_client_index; i++) {
1607  DATABASE_CLIENT* pclient = &pheader->client[i];
1608  for (j = 0; j < pclient->max_index; j++)
1609  if (pclient->open_record[j].handle) {
1610  int found = 0;
1611  for (k=0; k<uor.num_keys; k++) {
1612  if (uor.hkeys[k] == pclient->open_record[j].handle) {
1613  uor.counts[k]++;
1614  found = 1;
1615  break;
1616  }
1617  }
1618  if (!found) {
1619  uor.hkeys[uor.num_keys] = pclient->open_record[j].handle;
1620  uor.counts[uor.num_keys] = 1;
1621  uor.modes[uor.num_keys] = pclient->open_record[j].access_mode;
1622  uor.num_keys++;
1623  }
1624  }
1625  }
1626 
1627 #if 0
1628  for (i=0; i<uor.num_keys; i++)
1629  printf("index %d, handle %d, count %d, access mode %d\n", i, uor.hkeys[i], uor.counts[i], uor.modes[i]);
1630 #endif
1631 
1632  const KEY* proot = db_get_pkey(pheader, 0, &status, "db_validate_open_record", msg);
1633 
1634  if (proot) {
1635  db_scan_tree_locked(pheader, proot, 0, db_update_open_record_wlocked, &uor, msg);
1636  }
1637 
1638  if (uor.num_modified) {
1639  db_msg(msg, MINFO, "db_validate_open_records", "Corrected %d ODB entries", uor.num_modified);
1640  }
1641 
1642  free(uor.hkeys);
1643  free(uor.counts);
1644  free(uor.modes);
1645 
1646  return status;
1647 }
static int db_update_open_record_wlocked(const DATABASE_HEADER *xpheader, const KEY *xpkey, int level, void *voidp, db_err_msg **msg)
Definition: odb.cxx:1510
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_validate_sizes()

static void db_validate_sizes ( )
static

Definition at line 1402 of file odb.cxx.

1403 {
1404  /* validate size of data structures (miscompiled, 32/64 bit mismatch, etc */
1405 
1406  if (0) {
1407 #define S(x) printf("assert(sizeof(%-20s) == %6d);\n", #x, (int)sizeof(x))
1408  // basic data types
1409  S(char *);
1410  S(char);
1411  S(int);
1412  S(long int);
1413  S(float);
1414  S(double);
1415  S(BOOL);
1416  S(WORD);
1417  S(DWORD);
1418  S(INT);
1419  S(POINTER_T);
1420  S(midas_thread_t);
1421  // data buffers
1422  S(EVENT_REQUEST);
1423  S(BUFFER_CLIENT);
1424  S(BUFFER_HEADER);
1425  // history files
1426  S(HIST_RECORD);
1427  S(DEF_RECORD);
1428  S(INDEX_RECORD);
1429  S(TAG);
1430  // ODB shared memory structures
1431  S(KEY);
1432  S(KEYLIST);
1433  S(OPEN_RECORD);
1434  S(DATABASE_CLIENT);
1435  S(DATABASE_HEADER);
1436  // misc structures
1437  S(EVENT_HEADER);
1438  S(RUNINFO);
1439  S(EQUIPMENT_INFO);
1440  S(EQUIPMENT_STATS);
1441  S(BANK_HEADER);
1442  S(BANK);
1443  S(BANK32);
1444  S(ANA_OUTPUT_INFO);
1445  S(PROGRAM_INFO);
1446  S(ALARM_CLASS);
1447  S(ALARM);
1448  //S(CHN_SETTINGS);
1449  //S(CHN_STATISTICS);
1450 #undef S
1451  }
1452 
1453 #if 0
1455  printf("EQUIPMENT_INFO offset of event_id: %d\n", (int)((char*)&eq.event_id - (char*)&eq));
1456  printf("EQUIPMENT_INFO offset of eq_type: %d\n", (int)((char*)&eq.eq_type - (char*)&eq));
1457  printf("EQUIPMENT_INFO offset of event_limit: %d\n", (int)((char*)&eq.event_limit - (char*)&eq));
1458  printf("EQUIPMENT_INFO offset of num_subevents: %d\n", (int)((char*)&eq.num_subevents - (char*)&eq));
1459  printf("EQUIPMENT_INFO offset of status: %d\n", (int)((char*)&eq.status - (char*)&eq));
1460  printf("EQUIPMENT_INFO offset of hidden: %d\n", (int)((char*)&eq.hidden - (char*)&eq));
1461 #endif
1462 
1463  assert(sizeof(UINT8) == 1);
1464  assert(sizeof(INT8) == 1);
1465  assert(sizeof(UINT16) == 2);
1466  assert(sizeof(INT16) == 2);
1467  assert(sizeof(UINT32) == 4);
1468  assert(sizeof(INT32) == 4);
1469  assert(sizeof(UINT64) == 8);
1470  assert(sizeof(INT64) == 8);
1471 
1472 #ifdef OS_LINUX
1473  assert(sizeof(EVENT_REQUEST) == 16); // ODB v3
1474  assert(sizeof(BUFFER_CLIENT) == 256);
1475  assert(sizeof(BUFFER_HEADER) == 16444);
1476  assert(sizeof(HIST_RECORD) == 20);
1477  assert(sizeof(DEF_RECORD) == 40);
1478  assert(sizeof(INDEX_RECORD) == 12);
1479  assert(sizeof(TAG) == 40);
1480  assert(sizeof(KEY) == 68);
1481  assert(sizeof(KEYLIST) == 12);
1482  assert(sizeof(OPEN_RECORD) == 8);
1483  assert(sizeof(DATABASE_CLIENT) == 2112);
1484  assert(sizeof(DATABASE_HEADER) == 135232);
1485  assert(sizeof(EVENT_HEADER) == 16);
1486  //assert(sizeof(EQUIPMENT_INFO) == 696); has been moved to dynamic checking inside mhttpd.c
1487  assert(sizeof(EQUIPMENT_STATS) == 24);
1488  assert(sizeof(BANK_HEADER) == 8);
1489  assert(sizeof(BANK) == 8);
1490  assert(sizeof(BANK32) == 12);
1491  assert(sizeof(ANA_OUTPUT_INFO) == 792);
1492  assert(sizeof(PROGRAM_INFO) == 316);
1493  assert(sizeof(ALARM_CLASS) == 348);
1494  assert(sizeof(ALARM) == 452);
1495  //assert(sizeof(CHN_SETTINGS) == 648); // ODB v3
1496  //assert(sizeof(CHN_STATISTICS) == 56); // ODB v3
1497 #endif
1498 }
std::vector< FMT_ID > eq
Definition: mdump.cxx:58
unsigned short UINT16
Definition: midas.h:138
INT midas_thread_t
Definition: midas.h:179
char INT8
Definition: midas.h:137
short INT16
Definition: midas.h:139
int INT32
Definition: midas.h:141
unsigned char UINT8
Definition: midas.h:136
unsigned int UINT32
Definition: midas.h:140
#define S(x)
Definition: midas.h:1500
Definition: midas.h:1227
Definition: midas.h:1221
Definition: midas.h:1240
Here is the caller graph for this function:

◆ db_watch() [1/2]

INT db_watch ( HNDLE  hDB,
HNDLE  hKey,
void(*)(INT, INT, INT, void *)  dispatcher,
void *  info 
)

Watch an ODB subtree. The callback function gets called whenever a key in the watched subtree changes. The callback function receives the database handle and the key handle as parameters.

Parameters
hDBODB handle obtained via cm_get_experiment_database().
hKeyHandle for key at top of subtree to watch, zero for root.
(*dispatcher)Function which gets called when record is updated.The argument list composed of: HNDLE hDB, HNDLE hKey
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_NO_MEMORY, DB_NO_ACCESS, DB_STRUCT_SIZE_MISMATCH

Definition at line 13815 of file odb.cxx.

13816 {
13817  INT idx, status;
13818  KEY key;
13819  char str[256];
13820 
13821  /* check for valid key */
13822  assert(hKey);
13823 
13824  /* allocate new space for the local record list */
13825  if (_watch_list_entries == 0) {
13826  _watch_list = (WATCH_LIST *) malloc(sizeof(WATCH_LIST));
13827  memset(_watch_list, 0, sizeof(WATCH_LIST));
13828  if (_watch_list == NULL) {
13829  cm_msg(MERROR, "db_watch", "not enough memory");
13830  return DB_NO_MEMORY;
13831  }
13832 
13833  _watch_list_entries = 1;
13834  idx = 0;
13835  } else {
13836  /* check for a deleted entry */
13837  for (idx = 0; idx < _watch_list_entries; idx++)
13838  if (!_watch_list[idx].handle)
13839  break;
13840 
13841  /* if not found, create new one */
13842  if (idx == _watch_list_entries) {
13843  _watch_list = (WATCH_LIST *) realloc(_watch_list, sizeof(WATCH_LIST) * (_watch_list_entries + 1));
13844  if (_watch_list == NULL) {
13845  cm_msg(MERROR, "db_watch", "not enough memory");
13846  return DB_NO_MEMORY;
13847  }
13848 
13849  memset(&_watch_list[_watch_list_entries], 0, sizeof(WATCH_LIST));
13850 
13852  }
13853  }
13854 
13855  /* check key */
13856  status = db_get_key(hDB, hKey, &key);
13857  if (status != DB_SUCCESS) {
13859  db_get_path(hDB, hKey, str, sizeof(str));
13860  cm_msg(MERROR, "db_watch", "cannot get key %s", str);
13861  return DB_NO_MEMORY;
13862  }
13863 
13864  /* check for read access */
13865  if (!(key.access_mode & MODE_READ)) {
13867  db_get_path(hDB, hKey, str, sizeof(str));
13868  cm_msg(MERROR, "db_watch", "cannot get key %s", str);
13869  return DB_NO_ACCESS;
13870  }
13871 
13872  /* initialize record list */
13873  _watch_list[idx].handle = hKey;
13874  _watch_list[idx].hDB = hDB;
13875  _watch_list[idx].dispatcher = dispatcher;
13876  _watch_list[idx].info = info;
13877 
13878  /* add record entry in database structure */
13880 }
#define MODE_WATCH
Definition: midas.h:382
HNDLE handle
Definition: msystem.h:479
HNDLE hDB
Definition: msystem.h:480
void * info
Definition: msystem.h:482
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_watch() [2/2]

INT EXPRT db_watch ( HNDLE  hDB,
HNDLE  hKey,
void(*)(INT, INT, INT, void *info dispatcher,
void *  info 
)

◆ ends_with_ustring()

BOOL ends_with_ustring ( const char *  str,
const char *  suffix 
)

Definition at line 3212 of file odb.cxx.

3213 {
3214  int len_str = strlen(str);
3215  int len_suffix = strlen(suffix);
3216 
3217  // suffix is longer than the string
3218  if (len_suffix > len_str)
3219  return FALSE;
3220 
3221  return equal_ustring(str + len_str - len_suffix, suffix);
3222 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ equal_ustring()

BOOL equal_ustring ( const char *  str1,
const char *  str2 
)

Definition at line 3191 of file odb.cxx.

3192 {
3193  if (str1 == NULL && str2 != NULL)
3194  return FALSE;
3195  if (str1 != NULL && str2 == NULL)
3196  return FALSE;
3197  if (str1 == NULL && str2 == NULL)
3198  return TRUE;
3199  if (strlen(str1) != strlen(str2))
3200  return FALSE;
3201 
3202  while (*str1)
3203  if (toupper(*str1++) != toupper(*str2++))
3204  return FALSE;
3205 
3206  if (*str2)
3207  return FALSE;
3208 
3209  return TRUE;
3210 }

◆ extract_key()

const char* extract_key ( const char *  key_list,
char *  key_name,
int  key_name_length 
)

Definition at line 3177 of file odb.cxx.

3178 {
3179  int i = 0;
3180 
3181  if (*key_list == '/')
3182  key_list++;
3183 
3184  while (*key_list && *key_list != '/' && ++i < key_name_length)
3185  *key_name++ = *key_list++;
3186  *key_name = 0;
3187 
3188  return key_list;
3189 }
Here is the caller graph for this function:

◆ free_data()

static int free_data ( DATABASE_HEADER pheader,
void *  address,
INT  size,
const char *  caller 
)
static

Definition at line 451 of file odb.cxx.

452 {
453  if (size == 0)
454  return DB_SUCCESS;
455 
456  assert(address != pheader);
457 
458  /* quadword alignment for alpha CPU */
459  size = ALIGN8(size);
460 
461  /* smallest allocation size is 8 bytes to make sure we can always create a new FREE_DESCRIP in free_data() */
462  assert(size >= (int)sizeof(FREE_DESCRIP));
463 
464  FREE_DESCRIP *pprev = NULL;
465  FREE_DESCRIP *pfree = (FREE_DESCRIP *) address;
466  int pfree_offset = (POINTER_T) address - (POINTER_T) pheader;
467 
468  /* clear current block */
469  memset(address, 0, size);
470 
471  if (pheader->first_free_data == 0) {
472  /* if free list is empty, create the first free block, adjust pheader */
473  pfree->size = size;
474  pfree->next_free = 0;
475  pheader->first_free_data = pfree_offset;
476  /* nothing else to do */
477  return DB_SUCCESS;
478  } else if ((POINTER_T) address - (POINTER_T) pheader < pheader->first_free_data) {
479  /* if data comes before first free block, create new free block, adjust pheader */
480  pfree->size = size;
481  pfree->next_free = pheader->first_free_data;
482  pheader->first_free_data = pfree_offset;
483  /* maybe merge next free block into the new free block */
484  //printf("free_data: created new first free block, maybe merge with old first free block\n");
485  } else {
486  /* find last free block before current block */
487  pprev = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_data);
488 
489  while (pprev->next_free < pfree_offset) {
490  if (pprev->next_free == 0) {
491  /* add new free block at the end of the chain of free blocks */
492  //printf("free_data: adding new free block at the very end\n");
493  break;
494  }
495  if (!validate_free_data(pheader, pprev->next_free)) {
496  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);
497  return DB_CORRUPTED;
498  }
499 
500  pprev = (FREE_DESCRIP *) ((char *) pheader + pprev->next_free);
501  }
502 
503  pfree->size = size;
504  pfree->next_free = pprev->next_free;
505 
506  pprev->next_free = pfree_offset;
507  }
508 
509  /* try to melt adjacent free blocks after current block */
510  FREE_DESCRIP *pnext = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
511  if ((POINTER_T) pnext == (POINTER_T) pfree + pfree->size) {
512  //printf("free_data: merging first and second free block\n");
513  pfree->size += pnext->size;
514  pfree->next_free = pnext->next_free;
515 
516  memset(pnext, 0, pnext->size);
517  }
518 
519  /* try to melt adjacent free blocks before current block */
520  if (pprev && pprev->next_free == (POINTER_T) pprev - (POINTER_T) pheader + pprev->size) {
521  //printf("free_data: merging pprev and pfree\n");
522  pprev->size += pfree->size;
523  pprev->next_free = pfree->next_free;
524 
525  memset(pfree, 0, pfree->size);
526  }
527 
528  return DB_SUCCESS;
529 }
static int validate_free_data(DATABASE_HEADER *pheader, int free_data)
Definition: odb.cxx:339
Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_key()

static void free_key ( DATABASE_HEADER pheader,
void *  address,
INT  size 
)
static

Definition at line 280 of file odb.cxx.

281 {
282  FREE_DESCRIP *pfree, *pprev, *pnext;
283 
284  if (size == 0)
285  return;
286 
287  assert(address != pheader);
288 
289  /* quadword alignment for alpha CPU */
290  size = ALIGN8(size);
291 
292  pfree = (FREE_DESCRIP *) address;
293  pprev = NULL;
294 
295  /* clear current block */
296  memset(address, 0, size);
297 
298  /* if key comes before first free block, adjust pheader */
299  if ((POINTER_T) address - (POINTER_T) pheader < pheader->first_free_key) {
300  pfree->size = size;
301  pfree->next_free = pheader->first_free_key;
302  pheader->first_free_key = (POINTER_T) address - (POINTER_T) pheader;
303  } else {
304  /* find last free block before current block */
305  pprev = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_key);
306 
307  while (pprev->next_free < (POINTER_T) address - (POINTER_T) pheader) {
308  if (pprev->next_free <= 0) {
309  cm_msg(MERROR, "free_key", "database is corrupted: pprev=%p, pprev->next_free=%d", pprev, pprev->next_free);
310  return;
311  }
312  pprev = (FREE_DESCRIP *) ((char *) pheader + pprev->next_free);
313  }
314 
315  pfree->size = size;
316  pfree->next_free = pprev->next_free;
317 
318  pprev->next_free = (POINTER_T) pfree - (POINTER_T) pheader;
319  }
320 
321  /* try to melt adjacent free blocks after current block */
322  pnext = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
323  if ((POINTER_T) pnext == (POINTER_T) pfree + pfree->size) {
324  pfree->size += pnext->size;
325  pfree->next_free = pnext->next_free;
326 
327  memset(pnext, 0, pnext->size);
328  }
329 
330  /* try to melt adjacent free blocks before current block */
331  if (pprev && pprev->next_free == (POINTER_T) pprev - (POINTER_T) pheader + pprev->size) {
332  pprev->size += pfree->size;
333  pprev->next_free = pfree->next_free;
334 
335  memset(pfree, 0, pfree->size);
336  }
337 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ is_utf8()

static bool is_utf8 ( const char *  string)
static

Definition at line 825 of file odb.cxx.

826 {
827  if (!string)
828  return false;
829 
830  return ss_is_valid_utf8(string);
831 }
bool ss_is_valid_utf8(const char *string)
Definition: system.cxx:8007
Here is the call graph for this function:
Here is the caller graph for this function:

◆ json_ensure_decimal_dot()

static void json_ensure_decimal_dot ( char *  str)
static

Definition at line 9628 of file odb.cxx.

9629 {
9630  // sprintf "%.2e" can result in strings like "1,23e6" if
9631  // the user's locale has a comma for the decimal spearator.
9632  // However the JSON RFC requires a dot for the decimal.
9633  // This approach of "sprintf-then-replace" is much safer than
9634  // changing the user's locale, and much faster than the C++
9635  // approach of using a stringstream that we "imbue" with a C locale.
9636  char* comma = strchr(str, ',');
9637 
9638  if (comma != nullptr) {
9639  *comma = '.';
9640  }
9641 }
static double comma(double a, double b)
Definition: tinyexpr.c:248
Here is the call graph for this function:
Here is the caller graph for this function:

◆ json_write()

void EXPRT json_write ( char **  buffer,
int *  buffer_size,
int *  buffer_end,
int  level,
const char *  s,
int  quoted 
)

Definition at line 9528 of file odb.cxx.

9529 {
9530  int len, remain, xlevel;
9531 
9532  len = strlen(s);
9533  remain = *buffer_size - *buffer_end;
9534  assert(remain >= 0);
9535 
9536  xlevel = 2*level;
9537 
9538  while (10 + xlevel + 3*len > remain) {
9539  // reallocate the buffer
9540  int new_buffer_size = 2*(*buffer_size);
9541  if (new_buffer_size < 4*1024)
9542  new_buffer_size = 4*1024;
9543  //printf("reallocate: len %d, size %d, remain %d, allocate %d\n", len, *buffer_size, remain, new_buffer_size);
9544  assert(new_buffer_size > *buffer_size);
9545  *buffer = (char *)realloc(*buffer, new_buffer_size);
9546  assert(*buffer);
9547  *buffer_size = new_buffer_size;
9548  remain = *buffer_size - *buffer_end;
9549  assert(remain >= 0);
9550  }
9551 
9552  if (xlevel) {
9553  int i;
9554  for (i=0; i<xlevel; i++)
9555  (*buffer)[(*buffer_end)++] = ' ';
9556  }
9557 
9558  if (!quoted) {
9559  memcpy(*buffer + *buffer_end, s, len);
9560  *buffer_end += len;
9561  (*buffer)[*buffer_end] = 0; // NUL-terminate the buffer
9562  return;
9563  }
9564 
9565  char *bufptr = *buffer;
9566  int bufend = *buffer_end;
9567 
9568  bufptr[bufend++] = '"';
9569 
9570  while (*s) {
9571  switch (*s) {
9572  case '\"':
9573  bufptr[bufend++] = '\\';
9574  bufptr[bufend++] = '\"';
9575  s++;
9576  break;
9577  case '\\':
9578  bufptr[bufend++] = '\\';
9579  bufptr[bufend++] = '\\';
9580  s++;
9581  break;
9582 #if 0
9583  case '/':
9584  bufptr[bufend++] = '\\';
9585  bufptr[bufend++] = '/';
9586  s++;
9587  break;
9588 #endif
9589  case '\b':
9590  bufptr[bufend++] = '\\';
9591  bufptr[bufend++] = 'b';
9592  s++;
9593  break;
9594  case '\f':
9595  bufptr[bufend++] = '\\';
9596  bufptr[bufend++] = 'f';
9597  s++;
9598  break;
9599  case '\n':
9600  bufptr[bufend++] = '\\';
9601  bufptr[bufend++] = 'n';
9602  s++;
9603  break;
9604  case '\r':
9605  bufptr[bufend++] = '\\';
9606  bufptr[bufend++] = 'r';
9607  s++;
9608  break;
9609  case '\t':
9610  bufptr[bufend++] = '\\';
9611  bufptr[bufend++] = 't';
9612  s++;
9613  break;
9614  default:
9615  bufptr[bufend++] = *s++;
9616  }
9617  }
9618 
9619  bufptr[bufend++] = '"';
9620  bufptr[bufend] = 0; // NUL-terminate the buffer
9621 
9622  *buffer_end = bufend;
9623 
9624  remain = *buffer_size - *buffer_end;
9625  assert(remain > 0);
9626 }
Here is the caller graph for this function:

◆ json_write_anything()

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 
)

Definition at line 10388 of file odb.cxx.

10389 {
10390  int status;
10391  KEY key;
10392 
10393  status = db_get_key(hDB, hKey, &key);
10394  if (status != DB_SUCCESS)
10395  return status;
10396 
10397  if (key.type == TID_KEY) {
10398 
10399  json_write(buffer, buffer_size, buffer_end, 0, "{", 0);
10400 
10401  status = json_write_bare_subdir(hDB, hKey, buffer, buffer_size, buffer_end, level+1, flags, timestamp);
10402  if (status != DB_SUCCESS)
10403  return status;
10404 
10405  json_write(buffer, buffer_size, buffer_end, 0, "\n", 0);
10406  json_write(buffer, buffer_size, buffer_end, level, "}", 0);
10407 
10408  } else if (must_be_subdir) {
10409  json_write(buffer, buffer_size, buffer_end, 0, "{", 0);
10410  status = json_write_bare_key(hDB, hKey, key, buffer, buffer_size, buffer_end, level+1, flags, timestamp, false);
10411  if (status != DB_SUCCESS)
10412  return status;
10413  json_write(buffer, buffer_size, buffer_end, 0, "\n", 0);
10414  json_write(buffer, buffer_size, buffer_end, level, "}", 0);
10415  } else {
10416  status = db_copy_json_array(hDB, hKey, buffer, buffer_size, buffer_end);
10417 
10418  if (status != DB_SUCCESS)
10419  return status;
10420  }
10421 
10422  return DB_SUCCESS;
10423 }
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)
Definition: odb.cxx:10254
INT db_copy_json_array(HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end)
Definition: odb.cxx:10154
Here is the call graph for this function:
Here is the caller graph for this function:

◆ json_write_bare_key()

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

Definition at line 10254 of file odb.cxx.

10255 {
10256  int status;
10257  char link_buf[MAX_ODB_PATH]; // link_path points to link_buf
10258  char* link_path = NULL;
10259 
10260  HNDLE hLinkTarget = hLink;
10261 
10262  if (link.type == TID_LINK) {
10263  int size = sizeof(link_buf);
10264  status = db_get_link_data(hDB, hLink, link_buf, &size, TID_LINK);
10265  if (status != DB_SUCCESS)
10266  return status;
10267 
10268  //printf("link size %d, len %d, data [%s]\n", size, (int)strlen(link_buf), link_buf);
10269 
10270  if ((size > 0) && (strlen(link_buf) > 0)) {
10271  link_path = link_buf;
10272 
10273  // resolve the link, unless it is a link to an array element
10274  if ((flags & JSFLAG_FOLLOW_LINKS) && strchr(link_path, '[') == NULL) {
10275  status = db_find_key(hDB, 0, link_path, &hLinkTarget);
10276  if (status != DB_SUCCESS) {
10277  // dangling link to nowhere
10278  hLinkTarget = hLink;
10279  }
10280  }
10281  }
10282  }
10283 
10284  KEY link_target;
10285  status = db_get_key(hDB, hLinkTarget, &link_target);
10286  if (status != DB_SUCCESS)
10287  return status;
10288 
10289  if (flags & JSFLAG_OMIT_OLD) {
10290  if (link_target.last_written) {
10291  if (link_target.last_written < timestamp) {
10292  // omit old data
10293  return DB_SUCCESS;
10294  }
10295  }
10296  }
10297 
10298  if (need_comma) {
10299  json_write(buffer, buffer_size, buffer_end, 0, ",\n", 0);
10300  } else {
10301  json_write(buffer, buffer_size, buffer_end, 0, "\n", 0);
10302  }
10303 
10304  char link_name[MAX_ODB_PATH];
10305 
10306  strlcpy(link_name, link.name, sizeof(link_name));
10307 
10308  if (flags & JSFLAG_LOWERCASE) {
10309  for (int i=0; (i<(int)sizeof(link.name)) && link.name[i]; i++)
10310  link_name[i] = tolower(link.name[i]);
10311  }
10312 
10313  if ((flags & JSFLAG_LOWERCASE) && !(flags & JSFLAG_OMIT_NAMES)) {
10314  char buf[MAX_ODB_PATH];
10315  strlcpy(buf, link_name, sizeof(buf));
10316  strlcat(buf, "/name", sizeof(buf));
10317  json_write(buffer, buffer_size, buffer_end, level, buf, 1);
10318  json_write(buffer, buffer_size, buffer_end, 0, " : " , 0);
10319  json_write(buffer, buffer_size, buffer_end, 0, link.name, 1);
10320  json_write(buffer, buffer_size, buffer_end, 0, ",\n", 0);
10321  }
10322 
10323  if (link.type != TID_KEY && (flags & JSFLAG_SAVE_KEYS)) {
10324  char buf[MAX_ODB_PATH];
10325  strlcpy(buf, link_name, sizeof(buf));
10326  strlcat(buf, "/key", sizeof(buf));
10327  json_write(buffer, buffer_size, buffer_end, level, buf, 1);
10328  json_write(buffer, buffer_size, buffer_end, 0, " : " , 0);
10329  json_write_key(hDB, hLink, &link_target, link_path, buffer, buffer_size, buffer_end);
10330  json_write(buffer, buffer_size, buffer_end, 0, ",\n", 0);
10331  } else if ((link_target.type != TID_KEY) && !(flags & JSFLAG_OMIT_LAST_WRITTEN)) {
10332  char buf[MAX_ODB_PATH];
10333  strlcpy(buf, link_name, sizeof(buf));
10334  strlcat(buf, "/last_written", sizeof(buf));
10335  json_write(buffer, buffer_size, buffer_end, level, buf, 1);
10336  json_write(buffer, buffer_size, buffer_end, 0, " : " , 0);
10337  sprintf(buf, "%d", link_target.last_written);
10338  json_write(buffer, buffer_size, buffer_end, 0, buf, 0);
10339  json_write(buffer, buffer_size, buffer_end, 0, ",\n", 0);
10340  }
10341 
10342  json_write(buffer, buffer_size, buffer_end, level, link_name, 1);
10343  json_write(buffer, buffer_size, buffer_end, 0, " : " , 0);
10344 
10345  if (link_target.type == TID_KEY && !(flags & JSFLAG_RECURSE)) {
10346  json_write(buffer, buffer_size, buffer_end, 0, "{ }" , 0);
10347  } else {
10348  status = json_write_anything(hDB, hLinkTarget, buffer, buffer_size, buffer_end, level, 0, flags, timestamp);
10349  if (status != DB_SUCCESS)
10350  return status;
10351  }
10352 
10353  return DB_SUCCESS;
10354 }
static void json_write_key(HNDLE hDB, HNDLE hKey, const KEY *key, const char *link_path, char **buffer, int *buffer_size, int *buffer_end)
Definition: odb.cxx:9760
Here is the call graph for this function:
Here is the caller graph for this function:

◆ json_write_bare_subdir()

int json_write_bare_subdir ( HNDLE  hDB,
HNDLE  hKey,
char **  buffer,
int *  buffer_size,
int *  buffer_end,
int  level,
int  flags,
time_t  timestamp 
)

Definition at line 10356 of file odb.cxx.

10357 {
10358  if (level > MAX_ODB_PATH/2) {
10359  // max nesting level is limited by max odb path, where each subdirectory takes
10360  // at least 2 bytes - 1 byte directory name and 1 byte for "/"
10361  cm_msg(MERROR, "json_write_bare_subdir", "Max ODB subdirectory nesting level exceeded %d", level);
10362  return DB_TRUNCATED;
10363  }
10364 
10365  for (int i=0; ; i++) {
10366  int status;
10367 
10368  HNDLE hLink;
10369  status = db_enum_link(hDB, hKey, i, &hLink);
10370  if (status != DB_SUCCESS && !hLink)
10371  break;
10372 
10373  KEY link;
10374  status = db_get_link(hDB, hLink, &link);
10375  if (status != DB_SUCCESS)
10376  return status;
10377 
10378  bool need_comma = (i!=0);
10379 
10380  status = json_write_bare_key(hDB, hLink, link, buffer, buffer_size, buffer_end, level, flags, timestamp, need_comma);
10381  if (status != DB_SUCCESS)
10382  return status;
10383  }
10384 
10385  return DB_SUCCESS;
10386 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ json_write_data()

static void json_write_data ( char **  buffer,
int *  buffer_size,
int *  buffer_end,
int  level,
const KEY key,
const char *  p 
)
static

Definition at line 9643 of file odb.cxx.

9644 {
9645  char str[256];
9646  switch (key->type) {
9647  case TID_UINT8:
9648  sprintf(str, "%u", *(unsigned char*)p);
9649  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9650  break;
9651  case TID_INT8:
9652  sprintf(str, "%d", *(char*)p);
9653  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9654  break;
9655  case TID_CHAR:
9656  sprintf(str, "%c", *(char*)p);
9657  json_write(buffer, buffer_size, buffer_end, 0, str, 1);
9658  break;
9659  case TID_UINT16:
9660  sprintf(str, "\"0x%04x\"", *(WORD*)p);
9661  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9662  break;
9663  case TID_INT16:
9664  sprintf(str, "%d", *(short*)p);
9665  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9666  break;
9667  case TID_UINT32:
9668  sprintf(str, "\"0x%08x\"", *(DWORD*)p);
9669  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9670  break;
9671  case TID_INT32:
9672  sprintf(str, "%d", *(int*)p);
9673  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9674  break;
9675  case TID_UINT64:
9676  // encode as hex string
9677  sprintf(str, "\"0x%016llx\"", *(UINT64*)p);
9678  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9679  break;
9680  case TID_INT64:
9681  // encode as decimal string
9682  sprintf(str, "\"%lld\"", *(INT64*)p);
9683  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9684  break;
9685  case TID_BOOL:
9686  if (*(int*)p)
9687  json_write(buffer, buffer_size, buffer_end, 0, "true", 0);
9688  else
9689  json_write(buffer, buffer_size, buffer_end, 0, "false", 0);
9690  break;
9691  case TID_FLOAT: {
9692  float flt = (*(float*)p);
9693  if (isnan(flt))
9694  json_write(buffer, buffer_size, buffer_end, 0, "\"NaN\"", 0);
9695  else if (isinf(flt)) {
9696  if (flt > 0)
9697  json_write(buffer, buffer_size, buffer_end, 0, "\"Infinity\"", 0);
9698  else
9699  json_write(buffer, buffer_size, buffer_end, 0, "\"-Infinity\"", 0);
9700  } else if (flt == 0)
9701  json_write(buffer, buffer_size, buffer_end, 0, "0", 0);
9702  else if (flt == (int)flt) {
9703  sprintf(str, "%.0f", flt);
9705  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9706  } else {
9707  sprintf(str, "%.7e", flt);
9709  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9710  }
9711  break;
9712  }
9713  case TID_DOUBLE: {
9714  double dbl = (*(double*)p);
9715  if (isnan(dbl))
9716  json_write(buffer, buffer_size, buffer_end, 0, "\"NaN\"", 0);
9717  else if (isinf(dbl)) {
9718  if (dbl > 0)
9719  json_write(buffer, buffer_size, buffer_end, 0, "\"Infinity\"", 0);
9720  else
9721  json_write(buffer, buffer_size, buffer_end, 0, "\"-Infinity\"", 0);
9722  } else if (dbl == 0)
9723  json_write(buffer, buffer_size, buffer_end, 0, "0", 0);
9724  else if (dbl == (int)dbl) {
9725  sprintf(str, "%.0f", dbl);
9727  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9728  } else {
9729  sprintf(str, "%.16e", dbl);
9731  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9732  }
9733  break;
9734  }
9735  case TID_BITFIELD:
9736  json_write(buffer, buffer_size, buffer_end, 0, "(TID_BITFIELD value)", 1);
9737  break;
9738  case TID_STRING:
9739  // data is already NUL terminated // p[key.item_size-1] = 0; // make sure string is NUL terminated!
9740  json_write(buffer, buffer_size, buffer_end, 0, p, 1);
9741  break;
9742  case TID_ARRAY:
9743  json_write(buffer, buffer_size, buffer_end, 0, "(TID_ARRAY value)", 1);
9744  break;
9745  case TID_STRUCT:
9746  json_write(buffer, buffer_size, buffer_end, 0, "(TID_STRUCT value)", 1);
9747  break;
9748  case TID_KEY:
9749  json_write(buffer, buffer_size, buffer_end, 0, "{ }", 0);
9750  break;
9751  case TID_LINK:
9752  // data is already NUL terminated // p[key.item_size-1] = 0; // make sure string is NUL terminated!
9753  json_write(buffer, buffer_size, buffer_end, 0, p, 1);
9754  break;
9755  default:
9756  json_write(buffer, buffer_size, buffer_end, 0, "(TID_UNKNOWN value)", 1);
9757  }
9758 }
static void json_ensure_decimal_dot(char *str)
Definition: odb.cxx:9628
Here is the call graph for this function:
Here is the caller graph for this function:

◆ json_write_key()

static void json_write_key ( HNDLE  hDB,
HNDLE  hKey,
const KEY key,
const char *  link_path,
char **  buffer,
int *  buffer_size,
int *  buffer_end 
)
static

Definition at line 9760 of file odb.cxx.

9761 {
9762  char str[256]; // not used to store anything long, only numeric values like: "item_size: 100"
9763 
9764  json_write(buffer, buffer_size, buffer_end, 0, "{ ", 0);
9765 
9766  sprintf(str, "\"type\" : %d", key->type);
9767  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9768 
9769  if (link_path) {
9770  json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9771  json_write(buffer, buffer_size, buffer_end, 0, "link", 1);
9772  json_write(buffer, buffer_size, buffer_end, 0, ": ", 0);
9773  json_write(buffer, buffer_size, buffer_end, 0, link_path, 1);
9774  }
9775 
9776  if (key->num_values > 1) {
9777  json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9778 
9779  sprintf(str, "\"num_values\" : %d", key->num_values);
9780  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9781  }
9782 
9783  if (key->type == TID_STRING) {
9784  json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9785 
9786  sprintf(str, "\"item_size\" : %d", key->item_size);
9787  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9788  }
9789 
9790  if (key->notify_count > 0) {
9791  json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9792 
9793  sprintf(str, "\"notify_count\" : %d", key->notify_count);
9794  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9795  }
9796 
9797  json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9798 
9799  sprintf(str, "\"access_mode\" : %d", key->access_mode);
9800  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9801 
9802  json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9803 
9804  sprintf(str, "\"last_written\" : %d", key->last_written);
9805  json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9806 
9807  json_write(buffer, buffer_size, buffer_end, 0, " ", 0);
9808 
9809  json_write(buffer, buffer_size, buffer_end, 0, "}", 0);
9810 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ malloc_data()

static void* malloc_data ( DATABASE_HEADER pheader,
INT  size 
)
static

Definition at line 363 of file odb.cxx.

364 {
365  if (size == 0)
366  return NULL;
367 
368  assert(size > 0);
369 
370  /* quadword alignment for alpha CPU */
371  size = ALIGN8(size);
372 
373  /* smallest allocation size is 8 bytes to make sure we can always create a new FREE_DESCRIP in free_data() */
374  assert(size >= (int)sizeof(FREE_DESCRIP));
375 
376  if (!validate_free_data(pheader, pheader->first_free_data)) {
377  return NULL;
378  }
379 
380  /* search for free block */
381  FREE_DESCRIP *pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_data);
382  FREE_DESCRIP *pprev = NULL;
383  FREE_DESCRIP *pfound = NULL;
384 
385  while (1) {
386  //printf("malloc_data: pprev %p, pfree %p, next %d, size %d, want %d\n", pprev, pfree, pfree->next_free, pfree->size, size);
387 
388  if (pfree->size >= size) {
389  // we will use this block
390  pfound = pfree;
391  break;
392  }
393 
394  if (!pfree->next_free) {
395  // no more free blocks
396  return NULL;
397  }
398 
399  if (!validate_free_data(pheader, pfree->next_free)) {
400  // next_free is invalid
401  //printf("malloc_data: pprev %p, pfree %p, next %d, size %d, next is invalid\n", pprev, pfree, pfree->next_free, pfree->size);
402  return NULL;
403  }
404  pprev = pfree;
405  pfree = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
406  }
407 
408  //printf("malloc_data: pprev %p, pfound %p, size %d, want %d\n", pprev, pfound, pfound->size, size);
409 
410  assert(pfound != NULL);
411  assert(size <= pfound->size);
412 
413  /* if found block is first in list, correct pheader */
414  if (!pprev) {
415  if (size < pfree->size) {
416  /* free block is only used partially */
417  pheader->first_free_data += size;
418  pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_data);
419 
420  pfree->size = pfound->size - size;
421  pfree->next_free = pfound->next_free;
422  } else {
423  /* free block is used totally */
424  pheader->first_free_data = pfree->next_free;
425  }
426  } else {
427  /* check if free block is used totally */
428  if (pfound->size - size < (int) sizeof(FREE_DESCRIP)) {
429  /* delete this free block from the free blocks chain */
430  pprev->next_free = pfound->next_free;
431  } else {
432  /* decrease free block */
433  pfree = (FREE_DESCRIP *) ((char *) pfound + size);
434 
435  pfree->size = pfound->size - size;
436  pfree->next_free = pfound->next_free;
437 
438  pprev->next_free = (POINTER_T) pfree - (POINTER_T) pheader;
439  }
440  }
441 
442  assert((void*)pfound != (void*)pheader);
443 
444  /* zero memeory */
445  memset(pfound, 0, size);
446 
447  return pfound;
448 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ malloc_key()

static void* malloc_key ( DATABASE_HEADER pheader,
INT  size,
const char *  caller 
)
static

Definition at line 205 of file odb.cxx.

206 {
207  FREE_DESCRIP *pfree, *pfound, *pprev = NULL;
208 
209  if (size == 0)
210  return NULL;
211 
212  /* quadword alignment for alpha CPU */
213  size = ALIGN8(size);
214 
215  //printf("malloc_key(%d) from [%s]\n", size, caller);
216 
217  if (!db_validate_key_offset(pheader, pheader->first_free_key)) {
218  return NULL;
219  }
220 
221  /* search for free block */
222  pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_key);
223 
224  //printf("try free block %p size %d, next %d\n", pfree, pfree->size, pfree->next_free);
225 
226  while (pfree->size < size && pfree->next_free) {
227  if (!db_validate_key_offset(pheader, pfree->next_free)) {
228  return NULL;
229  }
230  pprev = pfree;
231  pfree = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
232  //printf("pfree %p size %d next_free %d\n", pfree, pfree->size, pfree->next_free);
233  }
234 
235  //printf("found free block %p size %d\n", pfree, pfree->size);
236 
237  /* return if not enough memory */
238  if (pfree->size < size)
239  return 0;
240 
241  pfound = pfree;
242 
243  /* if found block is first in list, correct pheader */
244  if (pfree == (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_key)) {
245  if (size < pfree->size) {
246  /* free block is only used partially */
247  pheader->first_free_key += size;
248  pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_key);
249 
250  pfree->size = pfound->size - size;
251  pfree->next_free = pfound->next_free;
252  } else {
253  /* free block is used totally */
254  pheader->first_free_key = pfree->next_free;
255  }
256  } else {
257  /* check if free block is used totally */
258  if (pfound->size - size < (int) sizeof(FREE_DESCRIP)) {
259  /* skip block totally */
260  pprev->next_free = pfound->next_free;
261  } else {
262  /* decrease free block */
263  pfree = (FREE_DESCRIP *) ((char *) pfound + size);
264 
265  pfree->size = pfound->size - size;
266  pfree->next_free = pfound->next_free;
267 
268  pprev->next_free = (POINTER_T) pfree - (POINTER_T) pheader;
269  }
270  }
271 
272  assert((void*)pfound != (void*)pheader);
273 
274  memset(pfound, 0, size);
275 
276  return pfound;
277 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ merge_records()

static void merge_records ( HNDLE  hDB,
HNDLE  hKey,
KEY pkey,
INT  level,
void *  info 
)
static

Definition at line 12663 of file odb.cxx.

12664 {
12665  char full_name[MAX_ODB_PATH];
12666  INT status, size;
12667  HNDLE hKeyInit;
12668  KEY initkey, key;
12669 
12670  /* avoid compiler warnings */
12671  status = level;
12672 
12673  /* compose name of init key */
12674  db_get_path(hDB, hKey, full_name, sizeof(full_name));
12675  *strchr(full_name, 'O') = 'I';
12676 
12677  /* if key in init record found, copy original data to init data */
12678  status = db_find_key(hDB, 0, full_name, &hKeyInit);
12679  if (status == DB_SUCCESS) {
12680  status = db_get_key(hDB, hKeyInit, &initkey);
12681  if (status != DB_SUCCESS) {
12682  cm_msg(MERROR, "merge_records", "merge_record error at \'%s\', db_get_key() status %d", full_name, status);
12683  return;
12684  }
12685  status = db_get_key(hDB, hKey, &key);
12686  if (status != DB_SUCCESS) {
12687  cm_msg(MERROR, "merge_records", "merge_record error at \'%s\', second db_get_key() status %d", full_name, status);
12688  return;
12689  }
12690 
12691  if (initkey.type != TID_KEY && initkey.type == key.type) {
12692  char* allocbuffer = NULL;
12693  char stackbuffer[10000];
12694  char* buffer = stackbuffer;
12695  size = sizeof(stackbuffer);
12696  while (1) {
12697  /* copy data from original key to new key */
12698  status = db_get_data(hDB, hKey, buffer, &size, initkey.type);
12699  if (status == DB_SUCCESS) {
12700  status = db_set_data(hDB, hKeyInit, buffer, initkey.total_size, initkey.num_values, initkey.type);
12701  if (status != DB_SUCCESS) {
12702  cm_msg(MERROR, "merge_records", "merge_record error at \'%s\', db_set_data() status %d", full_name, status);
12703  return;
12704  }
12705  break;
12706  }
12707  if (status == DB_TRUNCATED) {
12708  size *= 2;
12709  allocbuffer = (char *)realloc(allocbuffer, size);
12710  assert(allocbuffer != NULL);
12711  buffer = allocbuffer;
12712  continue;
12713  }
12714  cm_msg(MERROR, "merge_records", "aborting on unexpected failure of db_get_data(%s), status %d", full_name, status);
12715  abort();
12716  }
12717  if (allocbuffer)
12718  free(allocbuffer);
12719  }
12720  } else if (status == DB_NO_KEY) {
12721  /* do nothing */
12722  } else if (status == DB_INVALID_LINK) {
12723  status = db_find_link(hDB, 0, full_name, &hKeyInit);
12724  if (status == DB_SUCCESS) {
12725  size = sizeof(full_name);
12726  status = db_get_data(hDB, hKeyInit, full_name, &size, TID_LINK);
12727  }
12728  cm_msg(MERROR, "merge_records", "Invalid link \"%s\"", full_name);
12729  } else {
12730  cm_msg(MERROR, "merge_records", "aborting on unexpected failure of db_find_key(%s), status %d", full_name, status);
12731  abort();
12732  }
12733 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ name2c()

void name2c ( char *  str)

dox

Definition at line 9098 of file odb.cxx.

9106 {
9107  if (*str >= '0' && *str <= '9')
9108  *str = '_';
9109 
9110  while (*str) {
9111  if (!(*str >= 'a' && *str <= 'z') && !(*str >= 'A' && *str <= 'Z') && !(*str >= '0' && *str <= '9'))
9112  *str = '_';
9113  *str = (char) tolower(*str);
9114  str++;
9115  }
9116 }
Here is the caller graph for this function:

◆ print_key_info()

static INT print_key_info ( HNDLE  hDB,
HNDLE  hKey,
KEY pkey,
INT  level,
void *  info 
)
static

Definition at line 641 of file odb.cxx.

642 {
643  struct print_key_info_buf* buf = (struct print_key_info_buf*)info;
644  int i;
645 
646  char str[256];
647 
648  sprintf(str, "%08X %08X %08X ",
649  (int) (hKey - sizeof(DATABASE_HEADER)),
650  (int) (pkey->data - sizeof(DATABASE_HEADER)), (int) pkey->total_size);
651 
652  assert(strlen(str)+10 < sizeof(str));
653 
654  for (i = 0; i < level; i++)
655  strcat(str, " ");
656 
657  assert(strlen(str)+10 < sizeof(str));
658 
659  strcat(str, pkey->name);
660  strcat(str, "\n");
661 
662  assert(strlen(str)+10 < sizeof(str));
663 
664  //printf("str [%s]\n", str);
665 
666  add_to_buf(buf, str);
667 
668  return SUCCESS;
669 }
#define SUCCESS
Definition: mcstd.h:54
Here is the call graph for this function:
Here is the caller graph for this function:

◆ realloc_data()

static void* realloc_data ( DATABASE_HEADER pheader,
void *  address,
INT  old_size,
INT  new_size,
const char *  caller 
)
static

Definition at line 532 of file odb.cxx.

533 {
534  void *tmp = NULL;
535 
536  if (old_size) {
537  int status;
538  tmp = malloc(old_size);
539  if (tmp == NULL) {
540  cm_msg(MERROR, "realloc_data", "cannot malloc(%d), called from %s", old_size, caller);
541  return NULL;
542  }
543 
544  memcpy(tmp, address, old_size);
545 
546  status = free_data(pheader, address, old_size, caller);
547  if (status != DB_SUCCESS) {
548  free(tmp);
549  cm_msg(MERROR, "realloc_data", "cannot free_data(%p, %d), called from %s", address, old_size, caller);
550  return NULL;
551  }
552  }
553 
554  void *pnew = malloc_data(pheader, new_size);
555 
556  if (!pnew) {
557  if (tmp)
558  free(tmp);
559  cm_msg(MERROR, "realloc_data", "cannot malloc_data(%d), called from %s", new_size, caller);
560  return NULL;
561  }
562 
563  if (old_size) {
564  memcpy(pnew, tmp, old_size < new_size ? old_size : new_size);
565  free(tmp);
566  }
567 
568  return pnew;
569 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ strarrayindex()

void strarrayindex ( char *  odbpath,
int *  index1,
int *  index2 
)

Definition at line 3263 of file odb.cxx.

3263  {
3264  char* pc;
3265 
3266  *index1 = *index2 = 0;
3267  if (odbpath[strlen(odbpath) - 1] == ']') {
3268  if (strchr(odbpath, '[')) {
3269  if (*(strchr(odbpath, '[') + 1) == '*')
3270  *index1 = -1;
3271  else if (strchr((strchr(odbpath, '[') + 1), '.') ||
3272  strchr((strchr(odbpath, '[') + 1), '-')) {
3273  *index1 = atoi(strchr(odbpath, '[') + 1);
3274  pc = strchr(odbpath, '[') + 1;
3275  while (*pc != '.' && *pc != '-')
3276  pc++;
3277  while (*pc == '.' || *pc == '-')
3278  pc++;
3279  *index2 = atoi(pc);
3280  } else
3281  *index1 = atoi(strchr(odbpath, '[') + 1);
3282  }
3283 
3284  //remove everything after bracket
3285  *strchr(odbpath, '[') = 0;
3286  }
3287 }
Here is the caller graph for this function:

◆ strcomb()

char EXPRT * strcomb ( const char **  list)

Definition at line 574 of file odb.cxx.

576 {
577  INT i, j;
578  static char *str = NULL;
579 
580  /* counter number of chars */
581  for (i = 0, j = 0; list[i]; i++)
582  j += strlen(list[i]) + 1;
583  j += 1;
584 
585  if (str == NULL)
586  str = (char *) malloc(j);
587  else
588  str = (char *) realloc(str, j);
589 
590  str[0] = 0;
591  for (i = 0; list[i]; i++) {
592  strcat(str, list[i]);
593  strcat(str, "\n");
594  }
595 
596  return str;
597 }
static te_expr * list(state *s)
Definition: tinyexpr.c:567
Here is the call graph for this function:
Here is the caller graph for this function:

◆ strcomb1()

std::string EXPRT strcomb1 ( const char **  list)

Definition at line 601 of file odb.cxx.

603 {
604  std::string s;
605 
606  for (int i = 0; list[i]; i++) {
607  s += list[i];
608  s += "\n";
609  }
610 
611  return s;
612 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ strmatch()

BOOL strmatch ( char *  pattern,
char *  str 
)

Definition at line 3225 of file odb.cxx.

3225  {
3226  switch(*pattern){
3227  case 0:
3228  if(*str == 0){
3229  //end of pattern
3230  return true;
3231  }else
3232  return false;
3233  case '*':
3234  {
3235  int i=0;
3236  // check for end of the string
3237  if(pattern[1] == 0) return true;
3238  // loop on all possible matches
3239  while(str[i] != 0) if(strmatch(pattern + 1, str+(i++))) return true;
3240  return false;
3241  }
3242  case '?':
3243  if(*str == 0){
3244  //end of string
3245  return false;
3246  } else {
3247  return strmatch(pattern+1, str+1);
3248  }
3249  default:
3250  if(*str == 0){
3251  //end of string
3252  return false;
3253  } else if(toupper(*str) == toupper(*pattern)){
3254  //recursion
3255  return strmatch(pattern+1, str+1);
3256  } else {
3257  return false;
3258  }
3259  }
3260 }
Here is the caller graph for this function:

◆ validate_free_data()

static int validate_free_data ( DATABASE_HEADER pheader,
int  free_data 
)
static

Definition at line 339 of file odb.cxx.

340 {
341  if (free_data <= 0)
342  return 0;
343 
344  if (free_data < (int)sizeof(DATABASE_HEADER)) {
345  //printf("validate_free_data: failed: %d is inside the database header 0..%d\n", free_data, (int)sizeof(DATABASE_HEADER));
346  return 0;
347  }
348 
349  if (free_data < (int)sizeof(DATABASE_HEADER) + pheader->key_size) {
350  //printf("validate_free_data: failed: %d is inside key space %d..%d\n", free_data, (int)sizeof(DATABASE_HEADER), (int)sizeof(DATABASE_HEADER) + pheader->key_size);
351  return 0;
352  }
353 
354  if (free_data > (int)sizeof(DATABASE_HEADER) + pheader->key_size + pheader->data_size) {
355  //printf("validate_free_data: failed: %d is beyound end of odb %d+%d+%d = %d\n", free_data, (int)sizeof(DATABASE_HEADER), pheader->key_size, pheader->data_size, (int)sizeof(DATABASE_HEADER) + pheader->key_size + pheader->data_size);
356  return 0;
357  }
358 
359  return 1;
360 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ xml_encode()

void xml_encode ( char *  src,
int  size 
)

Definition at line 9304 of file odb.cxx.

9305 {
9306  int i;
9307  char *dst, *p;
9308 
9309  dst = (char *) malloc(size);
9310  if (dst == NULL)
9311  return;
9312 
9313  *dst = 0;
9314  for (i = 0; i < (int) strlen(src); i++) {
9315  switch (src[i]) {
9316  case '<':
9317  strlcat(dst, "&lt;", size);
9318  break;
9319  case '>':
9320  strlcat(dst, "&gt;", size);
9321  break;
9322  case '&':
9323  strlcat(dst, "&amp;", size);
9324  break;
9325  case '\"':
9326  strlcat(dst, "&quot;", size);
9327  break;
9328  case '\'':
9329  strlcat(dst, "&apos;", size);
9330  break;
9331  default:
9332  if ((int) strlen(dst) >= size) {
9333  free(dst);
9334  return;
9335  }
9336  p = dst + strlen(dst);
9337  *p = src[i];
9338  *(p + 1) = 0;
9339  }
9340  }
9341 
9342  strlcpy(src, dst, size);
9343 }
Here is the call graph for this function:

Variable Documentation

◆ _database

DATABASE* _database
static

Definition at line 57 of file odb.cxx.

◆ _database_entries

INT _database_entries = 0
static

Definition at line 58 of file odb.cxx.

◆ _global_open_count

int _global_open_count
static

Definition at line 12735 of file odb.cxx.

◆ _last_error_message

db_err_msg* _last_error_message = NULL
static

Definition at line 114 of file odb.cxx.

◆ _record_list

RECORD_LIST* _record_list
static

Definition at line 61 of file odb.cxx.

◆ _record_list_entries

INT _record_list_entries = 0
static

Definition at line 62 of file odb.cxx.

◆ _watch_list

WATCH_LIST* _watch_list
static

Definition at line 64 of file odb.cxx.

◆ _watch_list_entries

INT _watch_list_entries = 0
static

Definition at line 65 of file odb.cxx.