MIDAS
Loading...
Searching...
No Matches
ODB Functions (db_xxx)

Classes

struct  db_err_msg_struct
 
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 bool db_validate_key_offset (const DATABASE_HEADER *pheader, int offset)
 
static bool db_validate_data_offset (const DATABASE_HEADER *pheader, int offset)
 
static HNDLE db_pkey_to_hkey (const DATABASE_HEADER *pheader, const KEY *pkey)
 
static const KEYdb_get_pkey (const DATABASE_HEADER *pheader, HNDLE hKey, int *pstatus, const char *caller, db_err_msg **msg)
 
static const KEYdb_get_parent (const DATABASE_HEADER *pheader, const KEY *pkey, int *pstatus, const char *caller, db_err_msg **msg)
 
static const KEYLISTdb_get_pkeylist (const DATABASE_HEADER *pheader, const KEY *pkey, const char *caller, db_err_msg **msg, bool kludge_repair=false)
 
static INT db_find_key_locked (const DATABASE_HEADER *pheader, HNDLE hKey, const char *key_name, bool follow_links, HNDLE *subhKey, db_err_msg **msg)
 
static const KEYdb_find_pkey_locked (const DATABASE_HEADER *pheader, const KEY *pkey, const char *key_name, bool follow_links, 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_pkey (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 *pdb, 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_delete_key_locked (DATABASE *pdb, const KEY *pkey, int level, db_err_msg **msg)
 
static int db_set_value_wlocked (DATABASE *pdb, KEY *pkey_root, const char *key_name, const void *data, INT data_size, INT num_values, DWORD type, db_err_msg **msg)
 
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 DATABASEdb_lock_database (HNDLE hDB, int *pstatus, const char *caller, bool check_attached=true)
 
static void db_unlock_database (DATABASE *pdb, const char *caller)
 
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 INT print_key_info_locked (const DATABASE_HEADER *pheader, const KEY *pkey, INT level, void *info, db_err_msg **msg)
 
std::string db_show_mem (HNDLE hDB, 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_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 void db_print_pkey (const DATABASE_HEADER *pheader, const KEY *pkey, int recurse=0, const char *path=NULL, HNDLE parenthkeylist=0)
 
static void db_print_hkey (const DATABASE_HEADER *pheader, HNDLE hkey, int recurse=0, const char *path=NULL, HNDLE parenthkeylist=0)
 
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 (DATABASE *pdb, 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)
 
static int db_check_open_record (const DATABASE_HEADER *pheader, const KEY *pkey, db_err_msg **msg)
 
INT db_delete_key (HNDLE hDB, HNDLE hKey, BOOL follow_links)
 
INT db_delete_key (HNDLE hDB, HNDLE hKey)
 
INT db_delete (HNDLE hDB, HNDLE hKeyRoot, const char *odb_path)
 
INT db_find_key (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_keys (HNDLE hDB, HNDLE hKeyRoot, const 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_enum_locked (const DATABASE_HEADER *pheader, const KEY *pkey, std::vector< HNDLE > *sub_handles, std::vector< KEY > *sub_keys, bool follow_links, db_err_msg **msg)
 
INT EXPRT db_enum (HNDLE hDB, HNDLE hKeyRoot, std::vector< HNDLE > *sub_handles, std::vector< KEY > *sub_keys, bool follow_links)
 
INT EXPRT db_enum (HNDLE hDB, HNDLE hKeyRoot, const char *odb_path, std::vector< HNDLE > *sub_handles, std::vector< KEY > *sub_keys, bool follow_links)
 
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 (const DATABASE *pdb, const KEY *pkey, void **data, INT *total_size, INT base_align, INT *max_align, BOOL bSet, INT convert_flags, db_err_msg **msg)
 
static void db_recurse_record_tree_locked (const DATABASE *pdb, 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 41 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 1899 of file midas.h.

Typedef Documentation

◆ db_err_msg

typedef struct db_err_msg_struct db_err_msg

Definition at line 70 of file odb.cxx.

Function Documentation

◆ check_open_keys()

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

Definition at line 12765 of file odb.cxx.

12766{
12767 if (pkey->notify_count)
12769}
static int _global_open_count
Definition odb.cxx:12763
WORD notify_count
Definition midas.h:1035
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 12393 of file odb.cxx.

12401{
12402 if (rpc_is_remote())
12403 return rpc_call(RPC_DB_ADD_OPEN_RECORD, hDB, hKey, access_mode);
12404
12405#ifdef LOCAL_ROUTINES
12406 {
12407 INT i;
12408 int status;
12409
12410 if (hDB > _database_entries || hDB <= 0) {
12411 cm_msg(MERROR, "db_add_open_record", "invalid database handle");
12412 return DB_INVALID_HANDLE;
12413 }
12414
12415 db_err_msg* msg = NULL;
12416
12417 /* lock database */
12419
12420 DATABASE *pdb = &_database[hDB - 1];
12421 DATABASE_HEADER *pheader = pdb->database_header;
12423
12424 /* check if key is already open */
12425 for (i = 0; i < pclient->max_index; i++) {
12426 if (pclient->open_record[i].handle == hKey)
12427 break;
12428 }
12429
12430 if (i < pclient->max_index) {
12432 return DB_SUCCESS;
12433 }
12434
12435 /* not found, search free entry */
12436 for (i = 0; i < pclient->max_index; i++) {
12437 if (pclient->open_record[i].handle == 0)
12438 break;
12439 }
12440
12441 /* check if maximum number reached */
12442 if (i == MAX_OPEN_RECORDS) {
12444 return DB_NO_MEMORY;
12445 }
12446
12447 db_allow_write_locked(pdb, "db_add_open_record");
12448
12449 KEY *pkey = (KEY*)db_get_pkey(pheader, hKey, &status, "db_add_open_record", &msg);
12450
12451 if (!pkey) {
12453 if (msg)
12454 db_flush_msg(&msg);
12455 return status;
12456 }
12457
12458 if (i == pclient->max_index)
12459 pclient->max_index++;
12460
12461 pclient->open_record[i].handle = hKey;
12462 pclient->open_record[i].access_mode = access_mode;
12463
12464 /* increment notify_count */
12465 pkey->notify_count++;
12466
12467 pclient->num_open_records++;
12468
12469 /* set exclusive bit if requested */
12470 if (access_mode & MODE_WRITE)
12472
12474 }
12475#endif /* LOCAL_ROUTINES */
12476
12477 return DB_SUCCESS;
12478}
#define DB_INVALID_HANDLE
Definition midas.h:636
#define DB_SUCCESS
Definition midas.h:632
#define DB_NO_MEMORY
Definition midas.h:634
unsigned short int WORD
Definition mcstd.h:49
#define MODE_EXCLUSIVE
Definition midas.h:373
#define MODE_WRITE
Definition midas.h:371
#define MERROR
Definition midas.h:559
INT cm_msg(INT message_type, const char *filename, INT line, const char *routine, const char *format,...)
Definition midas.cxx:931
INT db_set_mode(HNDLE hDB, HNDLE hKey, WORD mode, BOOL recurse)
Definition odb.cxx:8040
INT db_allow_write_locked(DATABASE *p, const char *caller_name)
Definition odb.cxx:2619
static INT _database_entries
Definition odb.cxx:55
static const KEY * db_get_pkey(const DATABASE_HEADER *pheader, HNDLE hKey, int *pstatus, const char *caller, db_err_msg **msg)
Definition odb.cxx:959
DATABASE_CLIENT * db_get_my_client_locked(DATABASE *pdb)
Definition odb.cxx:1398
static void db_flush_msg(db_err_msg **msg)
Definition odb.cxx:193
static DATABASE * db_lock_database(HNDLE hDB, int *pstatus, const char *caller, bool check_attached=true)
Definition odb.cxx:2508
static void db_unlock_database(DATABASE *pdb, const char *caller)
Definition odb.cxx:2670
static DATABASE * _database
Definition odb.cxx:54
#define RPC_DB_ADD_OPEN_RECORD
Definition mrpc.h:73
bool rpc_is_remote(void)
Definition midas.cxx:12892
INT rpc_call(DWORD routine_id,...)
Definition midas.cxx:14115
HNDLE hKey
HNDLE hDB
main ODB handle
Definition mana.cxx:207
INT i
Definition mdump.cxx:32
int INT
Definition midas.h:129
#define MAX_OPEN_RECORDS
Definition midas.h:276
DWORD status
Definition odbhist.cxx:39
OPEN_RECORD open_record[MAX_OPEN_RECORDS]
Definition msystem.h:428
INT num_open_records
Definition msystem.h:423
DATABASE_HEADER * database_header
Definition msystem.h:454
Definition midas.h:1027
WORD access_mode
Definition midas.h:1034
WORD access_mode
Definition msystem.h:412
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 2619 of file odb.cxx.

2620{
2621 assert(p);
2622 if (p->protect && !p->protect_write) {
2623 int status;
2624 assert(p->lock_cnt > 0);
2625 assert(p->database_header != NULL);
2626 assert(p->protect_read);
2627 status = ss_shm_unprotect(p->shm_handle, &p->shm_adr, p->shm_size, TRUE, TRUE, caller_name);
2628 if (status != SS_SUCCESS) {
2629 cm_msg(MERROR, "db_allow_write_locked", "cannot write to ODB, ss_shm_unprotect(TRUE,TRUE) failed with status %d, aborting...", status);
2632 abort();
2633 }
2635 p->protect_read = TRUE;
2636 p->protect_write = TRUE;
2637 }
2638 return DB_SUCCESS;
2639}
#define SS_SUCCESS
Definition midas.h:664
INT ss_semaphore_release(HNDLE semaphore_handle)
Definition system.cxx:2853
INT ss_shm_unprotect(HNDLE handle, void **adr, size_t shm_size, BOOL read, BOOL write, const char *caller_name)
Definition system.cxx:1062
INT cm_msg_flush_buffer()
Definition midas.cxx:881
#define TRUE
Definition midas.h:182
BOOL protect
Definition msystem.h:461
HNDLE shm_size
Definition msystem.h:459
BOOL protect_read
Definition msystem.h:462
INT lock_cnt
Definition msystem.h:457
HNDLE semaphore
Definition msystem.h:456
HNDLE shm_handle
Definition msystem.h:460
BOOL protect_write
Definition msystem.h:463
void * shm_adr
Definition msystem.h:458
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 3143 of file odb.cxx.

3144{
3145 if (hDB > _database_entries || hDB <= 0) {
3146 cm_msg(MERROR, "db_check_client", "invalid database handle");
3147 return DB_INVALID_HANDLE;
3148 }
3149
3150 if (!_database[hDB - 1].attached) {
3151 cm_msg(MERROR, "db_check_client", "invalid database handle");
3152 return DB_INVALID_HANDLE;
3153 }
3154
3155 int status;
3156
3158
3159 db_err_msg* msg = NULL;
3160
3161 DATABASE *pdb = &_database[hDB - 1];
3162 DATABASE_HEADER *pheader = pdb->database_header;
3163
3164 const KEY* pkey = db_get_pkey(pheader, hKeyClient, &status, "db_check_client", &msg);
3165
3166 if (!pkey) {
3168 if (msg)
3169 db_flush_msg(&msg);
3170 return CM_NO_CLIENT;
3171 }
3172
3173 int client_pid = atoi(pkey->name);
3174
3175 const KEY* pkey_name = db_find_pkey_locked(pheader, pkey, "Name", true, &status, &msg);
3176
3177 if (!pkey_name) {
3179 if (msg)
3180 db_flush_msg(&msg);
3181 return CM_NO_CLIENT;
3182 }
3183
3184 char name[256];
3185 name[0] = 0;
3186 int size = sizeof(name);
3187 status = db_get_data_locked(pheader, pkey_name, 0, name, &size, TID_STRING, &msg);
3188
3189 //fprintf(stderr, "db_check_client: hkey %d, status %d, pid %d, name \'%s\'\n", hKeyClient, status, client_pid, name);
3190
3191 if (status != DB_SUCCESS) {
3193 if (msg)
3194 db_flush_msg(&msg);
3195 return CM_NO_CLIENT;
3196 }
3197
3198 bool dead = false;
3199 bool found = false;
3200
3201 /* loop through clients */
3202 for (int i = 0; i < pheader->max_client_index; i++) {
3203 DATABASE_CLIENT *pclient = &pheader->client[i];
3204 if (pclient->pid == client_pid) {
3205 found = true;
3206 break;
3207 }
3208 }
3209
3210 if (found) {
3211 /* check that the client is still running: PID still exists */
3212 if (!ss_pid_exists(client_pid)) {
3213 dead = true;
3214 }
3215 }
3216
3218
3219 if (!found || dead) {
3220 /* client not found : delete ODB stucture */
3221
3222 db_allow_write_locked(pdb, "db_check_client");
3223
3224 status = db_delete_client_info_wlocked(pdb, client_pid, &msg);
3225
3226 if (status != DB_SUCCESS)
3227 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);
3228 else if (!found)
3229 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);
3230 else if (dead)
3231 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);
3232
3234 }
3235
3237 if (msg)
3238 db_flush_msg(&msg);
3239
3240 return status;
3241}
#define CM_NO_CLIENT
Definition midas.h:584
#define MINFO
Definition midas.h:560
#define TID_STRING
Definition midas.h:346
BOOL ss_pid_exists(int pid)
Definition system.cxx:1442
static const KEY * db_find_pkey_locked(const DATABASE_HEADER *pheader, const KEY *pkey, const char *key_name, bool follow_links, int *pstatus, db_err_msg **msg)
Definition odb.cxx:4042
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:5277
static int db_delete_client_info_wlocked(DATABASE *pdb, int pid, db_err_msg **msg)
Definition odb.cxx:2844
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:142
#define name(x)
Definition midas_macro.h:24
DATABASE_CLIENT client[MAX_CLIENTS]
Definition msystem.h:443
INT max_client_index
Definition msystem.h:436
char name[NAME_LENGTH]
Definition midas.h:1030
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_check_open_record()

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

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_linksNot used
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_OPEN_RECORD

Definition at line 3758 of file odb.cxx.

3759{
3760 int status = 0;
3761
3762 while (1) {
3763#ifdef CHECK_OPEN_RECORD
3764 if (pkey->notify_count) {
3765 return DB_OPEN_RECORD;
3766 }
3767#endif
3768 if (pkey->parent_keylist == 0) // top level
3769 return DB_SUCCESS;
3770
3771 const KEY* pparent = db_get_parent(pheader, pkey, &status, "db_delete_key_locked", msg);
3772
3773 if (!pparent)
3774 return status;
3775
3776 pkey = pparent;
3777 };
3778
3779 return DB_SUCCESS;
3780}
#define DB_OPEN_RECORD
Definition midas.h:651
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:1057
INT parent_keylist
Definition midas.h:1037
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 13003 of file odb.cxx.

13004{
13005 char line[MAX_STRING_LENGTH];
13006 char title[MAX_STRING_LENGTH];
13007 char key_name[MAX_STRING_LENGTH];
13008 char info_str[MAX_STRING_LENGTH + 50];
13009 char *pc;
13010 const char *pold, *rec_str_orig;
13011 DWORD tid;
13012 INT i, j, n_data, string_length, status;
13013 HNDLE hKeyRoot, hKeyTest;
13014 KEY key;
13015 int bad_string_length;
13016
13017 if (rpc_is_remote())
13018 return rpc_call(RPC_DB_CHECK_RECORD, hDB, hKey, keyname, rec_str, correct);
13019
13020 /* check if record exists */
13021 status = db_find_key(hDB, hKey, keyname, &hKeyRoot);
13022
13023 /* create record if not */
13024 if (status == DB_NO_KEY) {
13025 if (correct)
13026 return db_create_record(hDB, hKey, keyname, rec_str);
13027 return DB_NO_KEY;
13028 }
13029
13030 assert(hKeyRoot);
13031
13032 title[0] = 0;
13033 rec_str_orig = rec_str;
13034
13035 db_get_key(hDB, hKeyRoot, &key);
13036 if (key.type == TID_KEY)
13037 /* get next subkey which is not of type TID_KEY */
13038 db_get_next_link(hDB, hKeyRoot, &hKeyTest);
13039 else
13040 /* test root key itself */
13041 hKeyTest = hKeyRoot;
13042
13043 if (hKeyTest == 0 && *rec_str != 0) {
13044 if (correct)
13045 return db_create_record(hDB, hKey, keyname, rec_str_orig);
13046
13047 return DB_STRUCT_MISMATCH;
13048 }
13049
13050 do {
13051 if (*rec_str == 0)
13052 break;
13053
13054 for (i = 0; *rec_str != '\n' && *rec_str && i < MAX_STRING_LENGTH; i++)
13055 line[i] = *rec_str++;
13056
13057 if (i == MAX_STRING_LENGTH) {
13058 cm_msg(MERROR, "db_check_record", "line too long");
13059 return DB_TRUNCATED;
13060 }
13061
13062 line[i] = 0;
13063 if (*rec_str == '\n')
13064 rec_str++;
13065
13066 /* check if it is a section title */
13067 if (line[0] == '[') {
13068 /* extract title and append '/' */
13069 strcpy(title, line + 1);
13070 if (strchr(title, ']'))
13071 *strchr(title, ']') = 0;
13072 if (title[0] && title[strlen(title) - 1] != '/')
13073 strcat(title, "/");
13074 } else {
13075 /* valid data line if it includes '=' and no ';' */
13076 if (strchr(line, '=') && line[0] != ';') {
13077 /* copy type info and data */
13078 pc = strchr(line, '=') + 1;
13079 while (*pc == ' ')
13080 pc++;
13081 strcpy(info_str, pc);
13082
13083 /* extract key name */
13084 *strchr(line, '=') = 0;
13085
13086 pc = &line[strlen(line) - 1];
13087 while (*pc == ' ')
13088 *pc-- = 0;
13089
13090 mstrlcpy(key_name, line, sizeof(key_name));
13091
13092 /* evaluate type info */
13093 strcpy(line, info_str);
13094 if (strchr(line, ' '))
13095 *strchr(line, ' ') = 0;
13096
13097 n_data = 1;
13098 if (strchr(line, '[')) {
13099 n_data = atol(strchr(line, '[') + 1);
13100 *strchr(line, '[') = 0;
13101 }
13102
13103 for (tid = 0; tid < TID_LAST; tid++)
13104 if (strcmp(rpc_tid_name(tid), line) == 0)
13105 break;
13106 if (tid == TID_LAST) {
13107 for (tid = 0; tid < TID_LAST; tid++)
13108 if (strcmp(rpc_tid_name_old(tid), line) == 0)
13109 break;
13110 }
13111
13112 string_length = 0;
13113
13114 if (tid == TID_LAST)
13115 cm_msg(MERROR, "db_check_record", "found unknown data type \"%s\" in ODB file", line);
13116 else {
13117 /* skip type info */
13118 pc = info_str;
13119 while (*pc != ' ' && *pc)
13120 pc++;
13121 while ((*pc == ' ' || *pc == ':') && *pc)
13122 pc++;
13123
13124 if (n_data > 1) {
13125 info_str[0] = 0;
13126 if (!*rec_str)
13127 break;
13128
13129 for (j = 0; *rec_str != '\n' && *rec_str; j++)
13130 info_str[j] = *rec_str++;
13131 info_str[j] = 0;
13132 if (*rec_str == '\n')
13133 rec_str++;
13134 }
13135
13136 for (i = 0; i < n_data; i++) {
13137 /* strip trailing \n */
13138 pc = &info_str[strlen(info_str) - 1];
13139 while (*pc == '\n' || *pc == '\r')
13140 *pc-- = 0;
13141
13142 if (tid == TID_STRING || tid == TID_LINK) {
13143 if (!string_length) {
13144 if (info_str[1] == '=')
13145 string_length = -1;
13146 else {
13147 pc = strchr(info_str, '[');
13148 if (pc != NULL)
13149 string_length = atoi(pc + 1);
13150 else
13151 string_length = -1;
13152 }
13153 if (string_length > MAX_STRING_LENGTH) {
13154 string_length = MAX_STRING_LENGTH;
13155 cm_msg(MERROR, "db_check_record", "found string exceeding MAX_STRING_LENGTH");
13156 }
13157 }
13158
13159 if (string_length == -1) {
13160 /* multi-line string */
13161 if (strstr(rec_str, "\n====#$@$#====\n") != NULL) {
13162 string_length = (POINTER_T) strstr(rec_str, "\n====#$@$#====\n") - (POINTER_T) rec_str + 1;
13163
13164 rec_str = strstr(rec_str, "\n====#$@$#====\n") + strlen("\n====#$@$#====\n");
13165 } else
13166 cm_msg(MERROR, "db_check_record", "found multi-line string without termination sequence");
13167 } else {
13168 if (strchr(info_str, ']'))
13169 pc = strchr(info_str, ']') + 1;
13170 else
13171 pc = info_str + 2;
13172 while (*pc && *pc != ' ')
13173 pc++;
13174 while (*pc && *pc == ' ')
13175 pc++;
13176
13177 /* limit string size */
13178 *(pc + string_length - 1) = 0;
13179 }
13180 } else {
13181 pc = info_str;
13182
13183 if (n_data > 1 && info_str[0] == '[') {
13184 pc = strchr(info_str, ']') + 1;
13185 while (*pc && *pc == ' ')
13186 pc++;
13187 }
13188 }
13189
13190 if (i < n_data - 1) {
13191 info_str[0] = 0;
13192 if (!*rec_str)
13193 break;
13194
13195 pold = rec_str;
13196
13197 for (j = 0; *rec_str != '\n' && *rec_str; j++)
13198 info_str[j] = *rec_str++;
13199 info_str[j] = 0;
13200 if (*rec_str == '\n')
13201 rec_str++;
13202
13203 /* test if valid data */
13204 if (tid != TID_STRING && tid != TID_LINK) {
13205 if (info_str[0] == 0 || (strchr(info_str, '=')
13206 && strchr(info_str, ':')))
13207 rec_str = pold;
13208 }
13209 }
13210 }
13211
13212 /* if rec_str contains key, but not ODB, return mismatch */
13213 if (!hKeyTest) {
13214 if (correct)
13215 return db_create_record(hDB, hKey, keyname, rec_str_orig);
13216
13217 return DB_STRUCT_MISMATCH;
13218 }
13219
13220 status = db_get_key(hDB, hKeyTest, &key);
13221 assert(status == DB_SUCCESS);
13222
13223 bad_string_length = 0;
13224
13225 if (key.type == TID_STRING) {
13226 //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);
13227 if (string_length > 0 && string_length != key.item_size) {
13228 bad_string_length = 1;
13229 }
13230 }
13231
13232 /* check rec_str vs. ODB key */
13233 if (!equal_ustring(key.name, key_name) || key.type != tid || key.num_values != n_data || bad_string_length) {
13234 //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);
13235 if (correct)
13236 return db_create_record(hDB, hKey, keyname, rec_str_orig);
13237
13238 return DB_STRUCT_MISMATCH;
13239 }
13240
13241 /* get next key in ODB */
13242 db_get_next_link(hDB, hKeyTest, &hKeyTest);
13243 }
13244 }
13245 }
13246 } while (TRUE);
13247
13248 return DB_SUCCESS;
13249}
#define DB_STRUCT_MISMATCH
Definition midas.h:655
#define DB_NO_KEY
Definition midas.h:643
#define DB_TRUNCATED
Definition midas.h:645
unsigned int DWORD
Definition mcstd.h:51
#define TID_KEY
Definition midas.h:349
#define TID_LINK
Definition midas.h:350
#define TID_LAST
Definition midas.h:354
#define MAX_STRING_LENGTH
Definition msystem.h:113
BOOL equal_ustring(const char *str1, const char *str2)
Definition odb.cxx:3285
INT db_get_next_link(HNDLE hDB, HNDLE hKey, HNDLE *subkey_handle)
Definition odb.cxx:5586
INT db_get_key(HNDLE hDB, HNDLE hKey, KEY *key)
Definition odb.cxx:6043
INT db_find_key(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
Definition odb.cxx:4256
INT db_create_record(HNDLE hDB, HNDLE hKey, const char *orig_key_name, const char *init_str)
Definition odb.cxx:12831
const char * rpc_tid_name_old(INT id)
Definition midas.cxx:11902
const char * rpc_tid_name(INT id)
Definition midas.cxx:11895
#define RPC_DB_CHECK_RECORD
Definition mrpc.h:90
KEY key
Definition mdump.cxx:34
INT HNDLE
Definition midas.h:132
#define POINTER_T
Definition midas.h:166
INT j
Definition odbhist.cxx:40
INT num_values
Definition midas.h:1029
DWORD type
Definition midas.h:1028
INT item_size
Definition midas.h:1033
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 7172 of file odb.cxx.

7173{
7174 /* check for write access */
7175 if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
7176 return DB_NO_ACCESS;
7177 }
7178
7179 if (pkey->type != type) {
7180 db_msg(msg, MERROR, caller, "\"%s\" is of type %s, not %s", db_get_path_pkey(pheader, pkey).c_str(), rpc_tid_name(pkey->type), rpc_tid_name(type));
7181 return DB_TYPE_MISMATCH;
7182 }
7183
7184 /* keys cannot contain data */
7185 if (pkey->type == TID_KEY) {
7186 db_msg(msg, MERROR, "db_set_data_index", "\"%s\" of type TID_KEY cannot contain data", db_get_path_pkey(pheader, pkey).c_str());
7187 return DB_TYPE_MISMATCH;
7188 }
7189
7190 /* check utf-8 encoding */
7191 if (pkey->type == TID_STRING || pkey->type == TID_LINK) {
7192 //printf("db_check_set_data_index for %s: utf8 check for odb \"%s\" value \"%s\"\n", caller, db_get_path_pkey(pheader, pkey).c_str(), data);
7193 const char* value = (const char*)data;
7194 if (!is_utf8(value)) {
7195 db_msg(msg, MERROR, "db_set_data_index", "\"%s\" index %d set to invalid UTF-8 Unicode string value \"%s\"", db_get_path_pkey(pheader, pkey).c_str(), idx, value);
7196 // just a warning for now. K.O.
7197 //return DB_TYPE_MISMATCH;
7198 }
7199 }
7200
7201 /* check for valid idx */
7202 if (idx < 0) {
7203 db_msg(msg, MERROR, caller, "\%s\" given invalid index %d", db_get_path_pkey(pheader, pkey).c_str(), idx);
7204 return DB_INVALID_PARAM;
7205 }
7206
7207 /* check for valid array element size: if new element size
7208 is different from existing size, ODB becomes corrupted */
7209 if (pkey->item_size != 0 && data_size != pkey->item_size) {
7210 db_msg(msg, MERROR, caller, "\"%s\" invalid element data size %d, expected %d", db_get_path_pkey(pheader, pkey).c_str(), data_size, pkey->item_size);
7211 return DB_TYPE_MISMATCH;
7212 }
7213
7214 return DB_SUCCESS;
7215}
#define DB_INVALID_PARAM
Definition midas.h:640
#define DB_NO_ACCESS
Definition midas.h:649
#define DB_TYPE_MISMATCH
Definition midas.h:646
static std::string db_get_path_pkey(const DATABASE_HEADER *pheader, const KEY *pkey)
Definition odb.cxx:4682
static bool is_utf8(const char *string)
Definition odb.cxx:851
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 7125 of file odb.cxx.

7126{
7127 /* check for write access */
7128 if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
7129 return DB_NO_ACCESS;
7130 }
7131
7132 if (pkey->type != type) {
7133 db_msg(msg, MERROR, caller, "\"%s\" is of type %s, not %s", db_get_path_pkey(pheader, pkey).c_str(), rpc_tid_name(pkey->type), rpc_tid_name(type));
7134 return DB_TYPE_MISMATCH;
7135 }
7136
7137 /* keys cannot contain data */
7138 if (pkey->type == TID_KEY) {
7139 db_msg(msg, MERROR, caller, "\"%s\" of type TID_KEY cannot contain data", db_get_path_pkey(pheader, pkey).c_str());
7140 return DB_TYPE_MISMATCH;
7141 }
7142
7143 if (type == TID_STRING || type == TID_LINK) {
7144 if (num_values > 1) {
7145 int item_size = pkey->item_size;
7146 if (data_size > 0 && num_values > 0)
7147 item_size = data_size/num_values;
7148 //printf("db_check_set_data for %s: utf8 check for odb \"%s\" string array size %d, item size %d\n", caller, db_get_path_pkey(pheader, pkey).c_str(), num_values, item_size);
7149 for (int i=0; i<num_values; i++) {
7150 const char* value = ((const char*)data) + i * item_size;
7151 //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_pkey(pheader, pkey).c_str(), num_values, item_size, i, value);
7152 if (!is_utf8(value)) {
7153 db_msg(msg, MERROR, caller, "\"%s\" index %d set to invalid UTF-8 Unicode string value \"%s\"", db_get_path_pkey(pheader, pkey).c_str(), i, value);
7154 // just a warning for now. K.O.
7155 //return DB_TYPE_MISMATCH;
7156 }
7157 }
7158 } else {
7159 const char* value = (const char*)data;
7160 //printf("db_check_set_data for %s: utf8 check for odb \"%s\" value \"%s\" size %d\n", caller, db_get_path_pkey(pheader, pkey).c_str(), value, data_size);
7161 if (!is_utf8(value)) {
7162 db_msg(msg, MERROR, caller, "\"%s\" set to invalid UTF-8 Unicode string value \"%s\"", db_get_path_pkey(pheader, pkey).c_str(), value);
7163 // just a warning for now. K.O.
7164 //return DB_TYPE_MISMATCH;
7165 }
7166 }
7167 }
7168
7169 return DB_SUCCESS;
7170}
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 2911 of file odb.cxx.

2912{
2913#ifdef LOCAL_ROUTINES
2914 int i;
2915 /* check online databases */
2916 for (i = 0; i < _database_entries; i++) {
2917 DATABASE *pdb = &_database[i];
2918 if (!pdb->attached) // empty slot
2919 continue;
2920
2921 db_lock_database(i + 1);
2922 db_allow_write_locked(pdb, "db_cleanup");
2923
2924 DATABASE_HEADER* pheader = pdb->database_header;
2926
2927 /* update the last_activity entry to show that we are alive */
2928 pclient->last_activity = actual_time;
2929
2930 /* don't check other clients if interval is stange */
2931 if (wrong_interval) {
2932 db_unlock_database(i + 1);
2933 continue;
2934 }
2935
2936 db_err_msg *msg = NULL;
2937
2938 /* now check other clients */
2939 int j;
2940 for (j = 0; j < pheader->max_client_index; j++) {
2941 DATABASE_CLIENT *pdbclient = &pheader->client[j];
2942 int client_pid = pdbclient->pid;
2943 if (client_pid == 0) // empty slot
2944 continue;
2945
2946 if (!ss_pid_exists(client_pid)) {
2947 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);
2948
2949 db_delete_client_wlocked(pheader, j, &msg);
2950 db_delete_client_info_wlocked(pdb, client_pid, &msg);
2951
2952 continue;
2953 }
2954
2955 /* now make again the check with the buffer locked */
2957 if ((pdbclient->watchdog_timeout &&
2958 actual_time > pdbclient->last_activity &&
2959 actual_time - pdbclient->last_activity > pdbclient->watchdog_timeout)
2960 ) {
2961 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)",
2962 pdbclient->name, pheader->name, client_pid,
2963 who,
2964 (actual_time - pdbclient->last_activity) / 1000.0,
2965 pdbclient->watchdog_timeout / 1000.0);
2966
2967 db_delete_client_wlocked(pheader, j, &msg);
2968 db_delete_client_info_wlocked(pdb, client_pid, &msg);
2969 }
2970 }
2971
2972 db_unlock_database(i + 1);
2973 if (msg)
2974 db_flush_msg(&msg);
2975 }
2976#endif
2977}
DWORD ss_millitime()
Definition system.cxx:3465
static void db_delete_client_wlocked(DATABASE_HEADER *pheader, int jclient, db_err_msg **msg)
Definition odb.cxx:2809
DWORD actual_time
Definition mfe.cxx:37
DWORD last_activity
Definition msystem.h:424
char name[NAME_LENGTH]
Definition msystem.h:418
DWORD watchdog_timeout
Definition msystem.h:425
char name[NAME_LENGTH]
Definition msystem.h:433
BOOL attached
Definition msystem.h:452
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 2981 of file odb.cxx.

2982{
2983 /* check online databases */
2984 int i;
2985 for (i = 0; i < _database_entries; i++) {
2986 if (_database[i].attached) {
2987 /* update the last_activity entry to show that we are alive */
2988
2989 db_lock_database(i + 1);
2990
2991 db_err_msg *msg = NULL;
2992
2993 DATABASE* pdb = &_database[i];
2994
2995 db_allow_write_locked(pdb, "db_cleanup2");
2996
2997 DWORD now = ss_millitime();
2998
2999 DATABASE_HEADER* pheader = pdb->database_header;
3001 pclient->last_activity = now;
3002
3003 /* now check other clients */
3004 int j;
3005 for (j = 0; j < pheader->max_client_index; j++) {
3006 DATABASE_CLIENT* pdbclient = &pheader->client[j];
3007 if (j == pdb->client_index) // do not check ourselves
3008 continue;
3009 if (!pdbclient->pid) // empty slot
3010 continue;
3011 if ((client_name == NULL || client_name[0] == 0
3012 || strncmp(pdbclient->name, client_name, strlen(client_name)) == 0)) {
3013 int client_pid = pdbclient->pid;
3014
3015 if (!ss_pid_exists(client_pid)) {
3016 db_msg(&msg, MINFO, "db_cleanup2", "Client \'%s\' on database \'%s\' pid %d does not exist and db_cleanup2 called by %s removed it",
3017 pdbclient->name, pheader->name,
3018 client_pid,
3019 who);
3020
3021 db_delete_client_wlocked(pheader, j, &msg);
3022 db_delete_client_info_wlocked(pdb, client_pid, &msg);
3023
3024 /* go again though whole list */
3025 j = 0;
3026 continue;
3027 }
3028
3029 DWORD interval;
3030 if (ignore_timeout)
3031 interval = 2 * WATCHDOG_INTERVAL;
3032 else
3033 interval = pdbclient->watchdog_timeout;
3034
3035 /* If client process has no activity, clear its buffer entry. */
3036
3037 if ((interval > 0 && now - pdbclient->last_activity > interval)) {
3038 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)",
3039 pdbclient->name, pheader->name,
3040 who,
3041 (now - pdbclient->last_activity) / 1000.0, interval / 1000.0);
3042
3043 db_delete_client_wlocked(pheader, j, &msg);
3044 db_delete_client_info_wlocked(pdb, client_pid, &msg);
3045
3046 /* go again though whole list */
3047 j = 0;
3048 continue;
3049 }
3050 }
3051 }
3052
3053 db_unlock_database(i + 1);
3054 if (msg)
3055 db_flush_msg(&msg);
3056 }
3057 }
3058}
#define WATCHDOG_INTERVAL
Definition midas.h:288
INT client_index
Definition msystem.h:453
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 2398 of file odb.cxx.

2415{
2416 INT status;
2417
2418 if (rpc_is_remote()) {
2420 if (status != DB_SUCCESS)
2421 return status;
2422 }
2423
2426
2427#ifdef LOCAL_ROUTINES
2428 {
2429 INT i;
2430
2431 for (i = _database_entries; i > 0; i--)
2433 }
2434#endif /* LOCAL_ROUTINES */
2435
2436 return DB_SUCCESS;
2437}
INT db_close_all_records()
Definition odb.cxx:13546
INT db_unwatch_all()
Definition odb.cxx:13950
INT db_close_database(HNDLE hDB)
Definition odb.cxx:2190
#define RPC_DB_CLOSE_ALL_DATABASES
Definition mrpc.h:55
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 13546 of file odb.cxx.

13547{
13548 INT i;
13549
13550 for (i = 0; i < _record_list_entries; i++) {
13551 if (_record_list[i].handle) {
13552 if (_record_list[i].access_mode & MODE_WRITE) {
13553 free(_record_list[i].copy);
13554 _record_list[i].copy = NULL;
13555 }
13556
13557 if (_record_list[i].access_mode & MODE_ALLOC) {
13558 free(_record_list[i].data);
13559 _record_list[i].data = NULL;
13560 }
13561
13562 memset(&_record_list[i], 0, sizeof(RECORD_LIST));
13563 }
13564 }
13565
13566 if (_record_list_entries > 0) {
13568 free(_record_list);
13569 _record_list = NULL;
13570 }
13571
13572 return DB_SUCCESS;
13573}
#define MODE_ALLOC
Definition midas.h:374
static INT _record_list_entries
Definition odb.cxx:59
static RECORD_LIST * _record_list
Definition odb.cxx:58
void * data
Definition msystem.h:476
void * copy
Definition msystem.h:477
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 2190 of file odb.cxx.

2191{
2192 if (rpc_is_remote())
2194
2195#ifdef LOCAL_ROUTINES
2196 else {
2197 INT destroy_flag, i, j;
2198 char xname[256];
2199
2200 if (hDB > _database_entries || hDB <= 0) {
2201 cm_msg(MERROR, "db_close_database", "invalid database handle %d", hDB);
2202 return DB_INVALID_HANDLE;
2203 }
2204
2205 /* flush database to disk */
2207
2208 /* first lock database */
2210
2211 DATABASE* pdb = &_database[hDB - 1];
2212
2213 if (!pdb->attached) {
2215 cm_msg(MERROR, "db_close_database", "database not attached");
2216 return DB_INVALID_HANDLE;
2217 }
2218
2219 DATABASE_HEADER *pheader = pdb->database_header;
2221
2222 db_allow_write_locked(pdb, "db_close_database");
2223
2224 /* close all open records */
2225 for (i = 0; i < pclient->max_index; i++)
2226 if (pclient->open_record[i].handle)
2227 db_remove_open_record_wlocked(pdb, pheader, pclient->open_record[i].handle);
2228
2229 /* mark entry in _database as empty */
2230 pdb->attached = FALSE;
2231
2232 /* clear entry from client structure in database header */
2233 memset(pclient, 0, sizeof(DATABASE_CLIENT));
2234
2235 /* calculate new max_client_index entry */
2236 for (i = MAX_CLIENTS - 1; i >= 0; i--)
2237 if (pheader->client[i].pid != 0)
2238 break;
2239 pheader->max_client_index = i + 1;
2240
2241 /* count new number of clients */
2242 for (i = MAX_CLIENTS - 1, j = 0; i >= 0; i--)
2243 if (pheader->client[i].pid != 0)
2244 j++;
2245 pheader->num_clients = j;
2246
2247 destroy_flag = (pheader->num_clients == 0);
2248
2249 /* flush shared memory to disk before it gets deleted */
2250 if (destroy_flag)
2251 ss_shm_flush(pheader->name, pdb->shm_adr, pdb->shm_size, pdb->shm_handle, true);
2252
2253 mstrlcpy(xname, pheader->name, sizeof(xname));
2254
2255 /* unmap shared memory, delete it if we are the last */
2256 ss_shm_close(xname, pdb->shm_adr, pdb->shm_size, pdb->shm_handle, destroy_flag);
2257
2258 pheader = NULL; // after ss_shm_close(), pheader points nowhere
2259 pdb->database_header = NULL; // ditto
2260
2261 /* unlock database */
2263
2264 /* delete semaphore */
2265 ss_semaphore_delete(pdb->semaphore, destroy_flag);
2266
2267 /* delete mutex */
2268 ss_mutex_delete(pdb->mutex);
2269
2270 /* update _database_entries */
2271 if (hDB == _database_entries)
2273
2274 if (_database_entries > 0)
2275 _database = (DATABASE *) realloc(_database, sizeof(DATABASE) * (_database_entries));
2276 else {
2277 free(_database);
2278 _database = NULL;
2279 }
2280
2281 /* if we are the last one, also delete other semaphores */
2282 if (destroy_flag) {
2283 //extern INT _semaphore_elog, _semaphore_alarm, _semaphore_history, _semaphore_msg;
2285
2286 if (_semaphore_elog)
2288 if (_semaphore_alarm)
2292 //if (_semaphore_msg)
2293 // ss_semaphore_delete(_semaphore_msg, TRUE);
2294 }
2295
2296 }
2297#endif /* LOCAL_ROUTINES */
2298
2299 return DB_SUCCESS;
2300}
#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:1178
INT ss_mutex_delete(MUTEX_T *mutex)
Definition system.cxx:3283
INT ss_semaphore_delete(HNDLE semaphore_handle, INT destroy_flag)
Definition system.cxx:2941
INT ss_shm_close(const char *name, void *adr, size_t shm_size, HNDLE handle, INT destroy_flag)
Definition system.cxx:757
INT db_flush_database(HNDLE hDB)
Definition odb.cxx:2306
static int db_remove_open_record_wlocked(DATABASE *pdb, DATABASE_HEADER *pheader, HNDLE hKey)
Definition odb.cxx:12482
#define RPC_DB_CLOSE_DATABASE
Definition mrpc.h:54
INT _semaphore_alarm
Definition midas.cxx:1478
INT _semaphore_elog
Definition midas.cxx:1479
INT _semaphore_history
Definition midas.cxx:1480
#define MAX_CLIENTS
Definition midas.h:274
MUTEX_T * mutex
Definition msystem.h:464
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 13505 of file odb.cxx.

13506{
13507#ifdef LOCAL_ROUTINES
13508 {
13509 INT i;
13510
13511 for (i = 0; i < _record_list_entries; i++)
13512 if (_record_list[i].handle == hKey && _record_list[i].hDB == hDB)
13513 break;
13514
13515 if (i == _record_list_entries)
13516 return DB_INVALID_HANDLE;
13517
13518 /* remove record entry from database structure */
13520
13521 /* free local memory */
13522 if (_record_list[i].access_mode & MODE_ALLOC) {
13523 free(_record_list[i].data);
13524 _record_list[i].data = NULL;
13525 }
13526
13527 if (_record_list[i].access_mode & MODE_WRITE) {
13528 free(_record_list[i].copy);
13529 _record_list[i].copy = NULL;
13530 }
13531
13532 memset(&_record_list[i], 0, sizeof(RECORD_LIST));
13533 }
13534#endif /* LOCAL_ROUTINES */
13535
13536 return DB_SUCCESS;
13537}
INT db_remove_open_record(HNDLE hDB, HNDLE hKey, BOOL lock)
Definition odb.cxx:12528
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 8230 of file odb.cxx.

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

10174{
10175 int size, asize;
10176 int status;
10177 char* data;
10178 int i;
10179 KEY key;
10180
10182 if (status != DB_SUCCESS)
10183 return status;
10184
10185 assert(key.type != TID_KEY);
10186
10187 if (key.num_values > 1) {
10188 json_write(buffer, buffer_size, buffer_end, 0, "[ ", 0);
10189 }
10190
10191 size = key.total_size;
10192
10193 asize = size;
10194 if (asize < 1024)
10195 asize = 1024;
10196
10197 data = (char *) malloc(asize);
10198 if (data == NULL) {
10199 cm_msg(MERROR, "db_save_json_key_data", "cannot allocate data buffer for %d bytes", asize);
10200 return DB_NO_MEMORY;
10201 }
10202
10203 data[0] = 0; // protect against TID_STRING that has key.total_size == 0.
10204
10205 status = db_get_data(hDB, hKey, data, &size, key.type);
10206 if (status != DB_SUCCESS) {
10207 free(data);
10208 return status;
10209 }
10210
10211 for (i = 0; i < key.num_values; i++) {
10212 char *p = data + key.item_size*i;
10213
10214 if (i != 0)
10215 json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
10216
10217 json_write_data(buffer, buffer_size, buffer_end, 0, &key, p);
10218 }
10219
10220 if (key.num_values > 1) {
10221 json_write(buffer, buffer_size, buffer_end, 0, " ]", 0);
10222 }
10223
10224 free(data);
10225 data = NULL;
10226
10227 return DB_SUCCESS;
10228}
INT db_get_data(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, DWORD type)
Definition odb.cxx:6563
static void json_write_data(char **buffer, int *buffer_size, int *buffer_end, int level, const KEY *key, const char *p)
Definition odb.cxx:9665
void json_write(char **buffer, int *buffer_size, int *buffer_end, int level, const char *s, int quoted)
Definition odb.cxx:9550
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 10242 of file odb.cxx.

10243{
10244 int status;
10245 KEY key;
10246
10248
10249 if (status != DB_SUCCESS)
10250 return status;
10251
10252 int size = key.item_size;
10253 char* data = (char*)malloc(size + 1); // extra byte for string NUL termination
10254 assert(data != NULL);
10255
10257
10258 if (status != DB_SUCCESS) {
10259 free(data);
10260 return status;
10261 }
10262
10263 assert(size <= key.item_size);
10264 data[key.item_size] = 0; // make sure data is NUL terminated, in case of strings.
10265
10266 json_write_data(buffer, buffer_size, buffer_end, 0, &key, data);
10267
10268 free(data);
10269
10270 return DB_SUCCESS;
10271}
INT db_get_data_index(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT idx, DWORD type)
Definition odb.cxx:6917
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 10442 of file odb.cxx.

10443{
10444 int status;
10445 bool unlock = false;
10446
10447 if (!rpc_is_remote()) {
10449 if (status != DB_SUCCESS) {
10450 return status;
10451 }
10452 unlock = true;
10453 }
10454
10456
10457 if (unlock) {
10459 }
10460
10461 return status;
10462}
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:10405
#define JS_LEVEL_0
Definition midas.h:1723
#define JSFLAG_FOLLOW_LINKS
Definition midas.h:1727
#define JS_MUST_BE_SUBDIR
Definition midas.h:1725
#define JSFLAG_SAVE_KEYS
Definition midas.h:1726
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 10529 of file odb.cxx.

10530{
10531 db_save_json_key_obsolete(hDB, hKey, 0, buffer, buffer_size, buffer_end, save_keys, follow_links, recurse);
10532 json_write(buffer, buffer_size, buffer_end, 0, "\n", 0);
10533 return DB_SUCCESS;
10534}
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:9834
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 10496 of file odb.cxx.

10497{
10498 int status;
10499 bool unlock = false;
10500
10501 if (!rpc_is_remote()) {
10503 if (status != DB_SUCCESS) {
10504 return status;
10505 }
10506 unlock = true;
10507 }
10508
10510
10511 if (unlock) {
10513 }
10514
10515 return status;
10516}
#define JSFLAG_RECURSE
Definition midas.h:1728
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 10464 of file odb.cxx.

10465{
10466 int status;
10468 if (omit_names)
10469 flags |= JSFLAG_OMIT_NAMES;
10470 if (omit_last_written)
10471 flags |= JSFLAG_OMIT_LAST_WRITTEN;
10472 if (omit_old_timestamp)
10473 flags |= JSFLAG_OMIT_OLD;
10474 if (!preserve_case)
10475 flags |= JSFLAG_LOWERCASE;
10476
10477 bool unlock = false;
10478
10479 if (!rpc_is_remote()) {
10481 if (status != DB_SUCCESS) {
10482 return status;
10483 }
10484 unlock = true;
10485 }
10486
10487 status = json_write_anything(hDB, hKey, buffer, buffer_size, buffer_end, JS_LEVEL_0, 0, flags, omit_old_timestamp);
10488
10489 if (unlock) {
10491 }
10492
10493 return status;
10494}
#define JSFLAG_LOWERCASE
Definition midas.h:1729
#define JSFLAG_OMIT_LAST_WRITTEN
Definition midas.h:1731
#define JSFLAG_OMIT_NAMES
Definition midas.h:1730
#define JSFLAG_OMIT_OLD
Definition midas.h:1732
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 9055 of file odb.cxx.

9056{
9057
9058 if (rpc_is_remote())
9059 return rpc_call(RPC_DB_COPY_XML, hDB, hKey, buffer, buffer_size, header);
9060
9061#ifdef LOCAL_ROUTINES
9062 {
9063 INT len;
9064 char *p;
9065 MXML_WRITER *writer;
9066
9067 /* open file */
9068 writer = mxml_open_buffer();
9069 if (writer == NULL) {
9070 cm_msg(MERROR, "db_copy_xml", "Cannot allocate buffer");
9071 return DB_NO_MEMORY;
9072 }
9073
9074 if (header) {
9075 std::string path = db_get_path(hDB, hKey);
9076
9077 /* write XML header */
9078 mxml_start_element(writer, "odb");
9079 mxml_write_attribute(writer, "root", path.c_str());
9080 mxml_write_attribute(writer, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
9081 mxml_write_attribute(writer, "xsi:noNamespaceSchemaLocation", "http://midas.psi.ch/odb.xsd");
9082
9083 db_save_xml_key(hDB, hKey, 0, writer);
9084 mxml_end_element(writer); // "odb"
9085 } else {
9086 KEY key;
9087 int status = db_get_key(hDB, hKey, &key);
9088 if (status != DB_SUCCESS)
9089 return status;
9090
9091 db_save_xml_key(hDB, hKey, 1, writer);
9092 }
9093
9094 p = mxml_close_buffer(writer);
9095 len = strlen(p) + 1;
9096 if (len > *buffer_size) {
9097 free(p);
9098 *buffer_size = 0;
9099 return DB_TRUNCATED;
9100 }
9101
9102 mstrlcpy(buffer, p, len);
9103 free(p);
9104 *buffer_size = len;
9105 }
9106#endif /* LOCAL_ROUTINES */
9107
9108 return DB_SUCCESS;
9109}
INT db_get_path(HNDLE hDB, HNDLE hKey, char *path, INT buf_size)
Definition odb.cxx:4775
INT db_save_xml_key(HNDLE hDB, HNDLE hKey, INT level, MXML_WRITER *writer)
Definition odb.cxx:9364
#define RPC_DB_COPY_XML
Definition mrpc.h:99
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 3392 of file odb.cxx.

3393{
3394
3395 if (rpc_is_remote())
3396 return rpc_call(RPC_DB_CREATE_KEY, hDB, hKey, key_name, type);
3397
3398#ifdef LOCAL_ROUTINES
3399 {
3400 int status;
3401
3402 if (hDB > _database_entries || hDB <= 0) {
3403 cm_msg(MERROR, "db_create_key", "invalid database handle");
3404 return DB_INVALID_HANDLE;
3405 }
3406
3407 if (!_database[hDB - 1].attached) {
3408 cm_msg(MERROR, "db_create_key", "invalid database handle");
3409 return DB_INVALID_HANDLE;
3410 }
3411
3412 /* lock database */
3414
3415 DATABASE* pdb = &_database[hDB - 1];
3416 DATABASE_HEADER* pheader = pdb->database_header;
3417
3418 db_err_msg *msg = NULL;
3419
3420 KEY* pkey = (KEY*)db_get_pkey(pheader, hKey, &status, "db_create_key", &msg);
3421
3422 if (!pkey) {
3424 if (msg)
3425 db_flush_msg(&msg);
3426 return DB_INVALID_HANDLE;
3427 }
3428
3429 db_allow_write_locked(pdb, "db_create_key");
3430
3431 KEY* newpkey = NULL;
3432
3433 status = db_create_key_wlocked(pheader, pkey, key_name, type, &newpkey, &msg);
3434
3436
3437 if (msg)
3438 db_flush_msg(&msg);
3439
3440 return status;
3441 }
3442#endif /* LOCAL_ROUTINES */
3443
3444 return DB_SUCCESS;
3445}
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:3449
#define RPC_DB_CREATE_KEY
Definition mrpc.h:56
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 3449 of file odb.cxx.

3450{
3451 int status;
3452
3453 if (pnewkey)
3454 *pnewkey = NULL;
3455
3456 if (parentKey== NULL) {
3457 parentKey = (KEY*) db_get_pkey(pheader, pheader->root_key, &status, "db_create_key_wlocked", msg);
3458 if (!parentKey) {
3459 return status;
3460 }
3461 }
3462
3463 //printf("db_create_key_wlocked: parent \"%s\", name \"%s\", type %d\n", db_get_path_pkey(pheader, parentKey).c_str(), key_name, type);
3464
3465 status = db_validate_name(key_name, TRUE, "db_create_key_wlocked", msg);
3466 if (status != DB_SUCCESS) {
3467 return status;
3468 }
3469
3470 /* check type */
3471 if (type <= 0 || type >= TID_LAST) {
3472 db_msg(msg, MERROR, "db_create_key", "invalid key type %d to create \'%s\' in \'%s\'", type, key_name, db_get_path_pkey(pheader, parentKey).c_str());
3473 return DB_INVALID_PARAM;
3474 }
3475
3476 const KEY* pdir = parentKey;
3477
3478 if (pdir->type != TID_KEY) {
3479 db_msg(msg, MERROR, "db_create_key", "cannot create \'%s\' in \'%s\' tid is %d, not a directory", key_name, db_get_path_pkey(pheader, pdir).c_str(), pdir->type);
3480 return DB_NO_KEY;
3481 }
3482
3483 KEY* pcreated = NULL;
3484
3485 const char* pkey_name = key_name;
3486 do {
3487 // key name is limited to NAME_LENGTH, but buffer has to be slightly longer
3488 // to prevent truncation before db_validate_name checks for correct length. K.O.
3489 char name[NAME_LENGTH+100];
3490
3491 /* extract single key from key_name */
3492 pkey_name = extract_key(pkey_name, name, sizeof(name));
3493
3494 status = db_validate_name(name, FALSE, "db_create_key", msg);
3495 if (status != DB_SUCCESS) {
3496 return status;
3497 }
3498
3499 /* do not allow empty names, like '/dir/dir//dir/' */
3500 if (name[0] == 0) {
3501 return DB_INVALID_PARAM;
3502 }
3503
3504 /* check if parent or current directory */
3505 if (strcmp(name, "..") == 0) {
3506 pdir = db_get_parent(pheader, pdir, &status, "db_create_key", msg);
3507 if (!pdir) {
3508 return status;
3509 }
3510 continue;
3511 }
3512 if (strcmp(name, ".") == 0)
3513 continue;
3514
3515 KEY* pprev = NULL;
3516 const KEY* pitem = db_enum_first_locked(pheader, pdir, msg);
3517
3518 while (pitem) {
3519 if (equal_ustring(name, pitem->name)) {
3520 break;
3521 }
3522 pprev = (KEY*)pitem;
3523 pitem = db_enum_next_locked(pheader, pdir, pitem, msg);
3524 }
3525
3526 if (!pitem) {
3527 /* not found: create new key */
3528
3529 /* check parent for write access */
3530 const KEY* pkeyparent = db_get_parent(pheader, pdir, &status, "db_create_key", msg);
3531 if (!pkeyparent) {
3532 return status;
3533 }
3534
3535 if (!(pkeyparent->access_mode & MODE_WRITE) || (pkeyparent->access_mode & MODE_EXCLUSIVE)) {
3536 return DB_NO_ACCESS;
3537 }
3538
3539 KEYLIST* pkeylist = (KEYLIST*)db_get_pkeylist(pheader, pdir, "db_create_key_wlocked", msg);
3540
3541 if (!pkeylist) {
3542 return DB_CORRUPTED;
3543 }
3544
3545 pkeylist->num_keys++;
3546
3547 if (*pkey_name == '/' || type == TID_KEY) {
3548 /* create new key with keylist */
3549 KEY* pkey = (KEY *) malloc_key(pheader, sizeof(KEY), "db_create_key_subdir");
3550
3551 if (pkey == NULL) {
3552 if (pkeylist->num_keys > 0)
3553 pkeylist->num_keys--;
3554
3555 db_msg(msg, MERROR, "db_create_key", "online database full while creating \'%s\' in \'%s\'", key_name, db_get_path_pkey(pheader, parentKey).c_str());
3556 return DB_FULL;
3557 }
3558
3559 /* append key to key list */
3560 if (pprev)
3561 pprev->next_key = (POINTER_T) pkey - (POINTER_T) pheader;
3562 else
3563 pkeylist->first_key = (POINTER_T) pkey - (POINTER_T) pheader;
3564
3565 /* set key properties */
3566 pkey->type = TID_KEY;
3567 pkey->num_values = 1;
3569 mstrlcpy(pkey->name, name, sizeof(pkey->name));
3570 pkey->parent_keylist = (POINTER_T) pkeylist - (POINTER_T) pheader;
3571
3572 /* find space for new keylist */
3573 pkeylist = (KEYLIST *) malloc_key(pheader, sizeof(KEYLIST), "db_create_key_B");
3574
3575 if (pkeylist == NULL) {
3576 db_msg(msg, MERROR, "db_create_key", "online database full while creating \'%s\' in \'%s'", key_name, db_get_path_pkey(pheader, parentKey).c_str());
3577 return DB_FULL;
3578 }
3579
3580 /* store keylist in data field */
3581 pkey->data = (POINTER_T) pkeylist - (POINTER_T) pheader;
3582 pkey->item_size = sizeof(KEYLIST);
3583 pkey->total_size = sizeof(KEYLIST);
3584
3585 pkeylist->parent = (POINTER_T) pkey - (POINTER_T) pheader;
3586 pkeylist->num_keys = 0;
3587 pkeylist->first_key = 0;
3588
3589 pcreated = pkey;
3590 pdir = pkey; // descend into newly created subdirectory
3591 } else {
3592 /* create new key with data */
3593 KEY* pkey = (KEY *) malloc_key(pheader, sizeof(KEY), "db_create_key_data");
3594
3595 if (pkey == NULL) {
3596 if (pkeylist->num_keys > 0)
3597 pkeylist->num_keys--;
3598
3599 db_msg(msg, MERROR, "db_create_key", "online database full while creating \'%s\' in \'%s\'", key_name, db_get_path_pkey(pheader, parentKey).c_str());
3600 return DB_FULL;
3601 }
3602
3603 /* append key to key list */
3604 if (pprev)
3605 pprev->next_key = (POINTER_T) pkey - (POINTER_T) pheader;
3606 else
3607 pkeylist->first_key = (POINTER_T) pkey - (POINTER_T) pheader;
3608
3609 pkey->type = type;
3610 pkey->num_values = 1;
3612 mstrlcpy(pkey->name, name, sizeof(pkey->name));
3613 pkey->parent_keylist = (POINTER_T) pkeylist - (POINTER_T) pheader;
3614
3615 /* allocate data */
3616 pkey->item_size = rpc_tid_size(type);
3617 if (pkey->item_size > 0) {
3618 void* data = malloc_data(pheader, pkey->item_size);
3619 if (data == NULL) {
3620 pkey->total_size = 0;
3621 db_msg(msg, MERROR, "db_create_key", "online database full while creating \'%s\' in \'%s\'", key_name, db_get_path_pkey(pheader, parentKey).c_str());
3622 return DB_FULL;
3623 }
3624
3625 pkey->total_size = pkey->item_size;
3626 pkey->data = (POINTER_T)data - (POINTER_T)pheader;
3627 } else {
3628 /* first data is empty */
3629 pkey->item_size = 0;
3630 pkey->total_size = 0;
3631 pkey->data = 0;
3632 }
3633 pcreated = pkey;
3634 }
3635 } else {
3636 /* key found: descend */
3637
3638 /* resolve links */
3639 if (pitem->type == TID_LINK && pkey_name[0]) {
3640 pdir = db_resolve_link_locked(pheader, pitem, &status, msg);
3641 if (!pdir) {
3642 return status;
3643 }
3644 continue;
3645 }
3646
3647 if (!(*pkey_name == '/')) {
3648 if (pitem->type != type) {
3649 db_msg(msg, MERROR, "db_create_key", "object of type %d already exists at \"%s\" while creating \'%s\' of type %d in \'%s\'", pitem->type, db_get_path_pkey(pheader, pitem).c_str(), key_name, type, db_get_path_pkey(pheader, parentKey).c_str());
3650 return DB_TYPE_MISMATCH;
3651 }
3652 //db_print_pkey(pheader, pitem);
3653
3654 if (pnewkey)
3655 *pnewkey = (KEY*)pitem;
3656
3657 return DB_KEY_EXIST;
3658 }
3659
3660 if (pitem->type != TID_KEY) {
3661 db_msg(msg, MERROR, "db_create_key", "path element \"%s\" in \"%s\" is not a subdirectory at \"%s\" while creating \'%s\' in \'%s\'", name, key_name, db_get_path_pkey(pheader, pitem).c_str(), key_name, db_get_path_pkey(pheader, parentKey).c_str());
3662 return DB_TYPE_MISMATCH;
3663 }
3664
3665 pdir = pitem;
3666 }
3667 } while (*pkey_name == '/');
3668
3669 assert(pcreated != NULL);
3670
3671 if (pnewkey)
3672 *pnewkey = pcreated;
3673
3674 return DB_SUCCESS;
3675}
#define DB_FULL
Definition midas.h:641
#define DB_KEY_EXIST
Definition midas.h:642
#define DB_CORRUPTED
Definition midas.h:654
#define MODE_DELETE
Definition midas.h:372
#define MODE_READ
Definition midas.h:370
static void * malloc_key(DATABASE_HEADER *pheader, INT size, const char *caller)
Definition odb.cxx:226
static const KEY * db_resolve_link_locked(const DATABASE_HEADER *, const KEY *, int *pstatus, db_err_msg **)
Definition odb.cxx:1119
static void * malloc_data(DATABASE_HEADER *pheader, INT size)
Definition odb.cxx:428
static const KEYLIST * db_get_pkeylist(const DATABASE_HEADER *pheader, const KEY *pkey, const char *caller, db_err_msg **msg, bool kludge_repair=false)
Definition odb.cxx:1011
static const KEY * db_enum_next_locked(const DATABASE_HEADER *pheader, const KEY *pdir, const KEY *pkey, db_err_msg **msg)
Definition odb.cxx:1111
static const KEY * db_enum_first_locked(const DATABASE_HEADER *pheader, const KEY *pkey, db_err_msg **msg)
Definition odb.cxx:1083
static int db_validate_name(const char *name, int maybe_path, const char *caller_name, db_err_msg **msg)
Definition odb.cxx:862
const char * extract_key(const char *key_list, char *key_name, int key_name_length)
Definition odb.cxx:3271
INT rpc_tid_size(INT id)
Definition midas.cxx:11888
#define NAME_LENGTH
Definition midas.h:272
INT next_key
Definition midas.h:1036
INT data
Definition midas.h:1031
INT num_keys
Definition midas.h:1043
INT parent
Definition midas.h:1042
INT first_key
Definition midas.h:1044
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 3688 of file odb.cxx.

3689{
3690 HNDLE hkey;
3691 int status;
3692
3693 if (rpc_is_remote())
3694 return rpc_call(RPC_DB_CREATE_LINK, hDB, hKey, link_name, destination);
3695
3696 if (destination == NULL) {
3697 cm_msg(MERROR, "db_create_link", "link destination name is NULL");
3698 return DB_INVALID_NAME;
3699 }
3700
3701 if (destination[0] != '/') {
3702 cm_msg(MERROR, "db_create_link", "link destination name \'%s\' should start with \'/\', relative links are forbidden", destination);
3703 return DB_INVALID_NAME;
3704 }
3705
3706 if (strlen(destination) < 1) {
3707 cm_msg(MERROR, "db_create_link", "link destination name \'%s\' is too short", destination);
3708 return DB_INVALID_NAME;
3709 }
3710
3711 if ((destination[0] == '/') && (destination[1] == 0)) {
3712 cm_msg(MERROR, "db_create_link", "links to \"/\" are forbidden");
3713 return DB_INVALID_NAME;
3714 }
3715
3716 /* check if destination exists */
3717 status = db_find_key(hDB, hKey, destination, &hkey);
3718 if (status != DB_SUCCESS) {
3719 cm_msg(MERROR, "db_create_link", "Link destination \"%s\" does not exist", destination);
3720 return DB_NO_KEY;
3721 }
3722
3723 //printf("db_create_link: [%s] hkey %d\n", destination, hkey);
3724
3725 /* check if link already exists */
3726 status = db_find_link(hDB, hKey, link_name, &hkey);
3727 if (status != DB_SUCCESS) {
3728 // create new link
3729 status = db_set_value(hDB, hKey, link_name, destination, strlen(destination) + 1, 1, TID_LINK);
3730 } else {
3731 // check if key is TID_LINK
3732 KEY key;
3733 db_get_key(hDB, hkey, &key);
3734 if (key.type != TID_LINK) {
3735 cm_msg(MERROR, "db_create_link", "Existing key \"%s\" is not a link", link_name);
3736 return DB_KEY_EXIST;
3737 }
3738
3739 // modify existing link
3740 status = db_set_link_data(hDB, hkey, destination, strlen(destination)+1, 1, TID_LINK);
3741 }
3742
3743 return status;
3744}
#define DB_INVALID_NAME
Definition midas.h:635
INT db_find_link(HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
Definition odb.cxx:4293
INT db_set_link_data(HNDLE hDB, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type)
Definition odb.cxx:7449
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:5028
#define RPC_DB_CREATE_LINK
Definition mrpc.h:57
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:3027
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:13322
int main()
Definition hwtest.cxx:23
void ** info
Definition fesimdaq.cxx:41
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 12831 of file odb.cxx.

12832{
12833 char key_name[256], *buffer;
12834 INT status, size, buffer_size;
12835 HNDLE hKeyTmp, hKeyTmpO, hKeyOrig, hSubkey;
12836
12837 if (rpc_is_remote())
12838 return rpc_call(RPC_DB_CREATE_RECORD, hDB, hKey, orig_key_name, init_str);
12839
12840 /* make this function atomic */
12842
12843 /* strip trailing '/' */
12844 mstrlcpy(key_name, orig_key_name, sizeof(key_name));
12845 if (strlen(key_name) > 1 && key_name[strlen(key_name) - 1] == '/')
12846 key_name[strlen(key_name) - 1] = 0;
12847
12848 /* merge temporay record and original record */
12849 status = db_find_key(hDB, hKey, key_name, &hKeyOrig);
12850 if (status == DB_SUCCESS) {
12851 assert(hKeyOrig != 0);
12852#ifdef CHECK_OPEN_RECORD
12853 /* check if key or subkey is opened */
12854 _global_open_count = 0; // FIXME: this is not thread safe
12855 db_scan_tree_link(hDB, hKeyOrig, 0, check_open_keys, NULL);
12856 if (_global_open_count) {
12858 return DB_OPEN_RECORD;
12859 }
12860#endif
12861 /* create temporary records */
12862 std::string str = "/System/Tmp/" + ss_tid_to_string(ss_gettid()) + "I";
12863 //printf("db_create_record str [%s]\n", str);
12864 db_delete(hDB, 0, str.c_str());
12865 db_create_key(hDB, 0, str.c_str(), TID_KEY);
12866 status = db_find_key(hDB, 0, str.c_str(), &hKeyTmp);
12867 if (status != DB_SUCCESS) {
12869 return status;
12870 }
12871
12872 str = "/System/Tmp/" + ss_tid_to_string(ss_gettid()) + "O";
12873 //printf("db_create_record str [%s]\n", str);
12874 db_delete(hDB, 0, str.c_str());
12875 db_create_key(hDB, 0, str.c_str(), TID_KEY);
12876 status = db_find_key(hDB, 0, str.c_str(), &hKeyTmpO);
12877 if (status != DB_SUCCESS) {
12879 return status;
12880 }
12881
12882 status = db_paste(hDB, hKeyTmp, init_str);
12883 if (status != DB_SUCCESS) {
12885 return status;
12886 }
12887
12888 buffer_size = 10000;
12889 buffer = (char *) malloc(buffer_size);
12890 assert(buffer != NULL);
12891
12892 do {
12893 size = buffer_size;
12894 status = db_copy(hDB, hKeyOrig, buffer, &size, "");
12895 if (status == DB_TRUNCATED) {
12896 buffer_size += 10000;
12897 buffer = (char *) realloc(buffer, buffer_size);
12898 assert(buffer != NULL);
12899 continue;
12900 }
12901 if (status != DB_SUCCESS) {
12902 free(buffer);
12904 return status;
12905 }
12906
12907 } while (status != DB_SUCCESS);
12908
12909 status = db_paste(hDB, hKeyTmpO, buffer);
12910 if (status != DB_SUCCESS) {
12911 free(buffer);
12913 return status;
12914 }
12915
12916 /* merge temporay record and original record */
12917 db_scan_tree_link(hDB, hKeyTmpO, 0, merge_records, NULL);
12918
12919 /* delete original record */
12920 while (1) {
12921 db_enum_link(hDB, hKeyOrig, 0, &hSubkey);
12922 if (!hSubkey)
12923 break;
12924
12926 if (status != DB_SUCCESS) {
12927 free(buffer);
12929 return status;
12930 }
12931 }
12932
12933 /* copy merged record to original record */
12934 do {
12935 size = buffer_size;
12936 status = db_copy(hDB, hKeyTmp, buffer, &size, "");
12937 if (status == DB_TRUNCATED) {
12938 buffer_size += 10000;
12939 buffer = (char *) realloc(buffer, buffer_size);
12940 continue;
12941 }
12942 if (status != DB_SUCCESS) {
12943 free(buffer);
12945 return status;
12946 }
12947
12948 } while (status != DB_SUCCESS);
12949
12950 status = db_paste(hDB, hKeyOrig, buffer);
12951 if (status != DB_SUCCESS) {
12952 free(buffer);
12954 return status;
12955 }
12956
12957 /* delete temporary records */
12958 db_delete_key(hDB, hKeyTmp);
12959 db_delete_key(hDB, hKeyTmpO);
12960
12961 free(buffer);
12962 buffer = NULL;
12963 } else if (status == DB_NO_KEY) {
12964 /* create fresh record */
12965 db_create_key(hDB, hKey, key_name, TID_KEY);
12966 status = db_find_key(hDB, hKey, key_name, &hKeyTmp);
12967 if (status != DB_SUCCESS) {
12969 return status;
12970 }
12971
12972 status = db_paste(hDB, hKeyTmp, init_str);
12973 if (status != DB_SUCCESS) {
12975 return status;
12976 }
12977 } else {
12978 cm_msg(MERROR, "db_create_record", "aborting on unexpected failure of db_find_key(%s), status %d", key_name, status);
12979 abort();
12980 }
12981
12983
12984 return DB_SUCCESS;
12985}
std::string ss_tid_to_string(midas_thread_t thread_id)
Definition system.cxx:1643
midas_thread_t ss_gettid(void)
Definition system.cxx:1591
static void check_open_keys(HNDLE hDB, HNDLE hKey, KEY *pkey, INT level, void *info)
Definition odb.cxx:12765
INT db_delete_key(HNDLE hDB, HNDLE hKey, BOOL follow_links)
Definition odb.cxx:3933
INT db_create_key(HNDLE hDB, HNDLE hKey, const char *key_name, DWORD type)
Definition odb.cxx:3392
INT db_scan_tree_link(HNDLE hDB, HNDLE hKey, INT level, void(*callback)(HNDLE, HNDLE, KEY *, INT, void *), void *info)
Definition odb.cxx:4627
INT db_paste(HNDLE hDB, HNDLE hKeyRoot, const char *buffer)
Definition odb.cxx:8505
INT db_delete(HNDLE hDB, HNDLE hKeyRoot, const char *odb_path)
Definition odb.cxx:3999
static void merge_records(HNDLE hDB, HNDLE hKey, KEY *pkey, INT level, void *info)
Definition odb.cxx:12690
#define RPC_DB_CREATE_RECORD
Definition mrpc.h:81
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_delete()

INT EXPRT db_delete ( HNDLE  hDB,
HNDLE  hKeyRoot,
const char *  odb_path 
)

Definition at line 3999 of file odb.cxx.

4000{
4001 if (rpc_is_remote()) {
4002 HNDLE hKey;
4003 int status = db_find_link(hDB, hKeyRoot, odb_path, &hKey);
4004 if (status != DB_SUCCESS)
4005 return status;
4006 return db_delete_key(hDB, hKey);
4007 }
4008
4009#ifdef LOCAL_ROUTINES
4010
4011 int status = DB_SUCCESS;
4012
4013 DATABASE* pdb = db_lock_database(hDB, &status, "db_delete");
4014
4015 if (!pdb)
4016 return status;
4017
4018 db_err_msg *msg = NULL;
4019
4020 const KEY* pkeyroot = db_get_pkey(pdb->database_header, hKeyRoot, &status, "db_delete", &msg);
4021
4022 if (pkeyroot) {
4023 const KEY* pkey = db_find_pkey_locked(pdb->database_header, pkeyroot, odb_path, false, &status, &msg);
4024
4025 if (pkey) {
4026 status = db_delete_key_locked(pdb, pkey, 0, &msg);
4027 }
4028 }
4029
4030 db_unlock_database(pdb, "db_delete");
4031
4032 if (msg)
4033 db_flush_msg(&msg);
4034
4035 return status;
4036#else
4037 return DB_SUCCESS;
4038#endif
4039}
static int db_delete_key_locked(DATABASE *pdb, const KEY *pkey, int level, db_err_msg **msg)
Definition odb.cxx:3782
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 2876 of file odb.cxx.

2877{
2878#ifdef LOCAL_ROUTINES
2879 if (hDB > _database_entries || hDB <= 0) {
2880 cm_msg(MERROR, "db_delete_client_info", "invalid database handle");
2881 return DB_INVALID_HANDLE;
2882 }
2883
2884 if (!_database[hDB - 1].attached) {
2885 cm_msg(MERROR, "db_delete_client_info", "invalid database handle");
2886 return DB_INVALID_HANDLE;
2887 }
2888
2889 /* lock database */
2891
2892 DATABASE *pdb = &_database[hDB - 1];
2893
2894 db_allow_write_locked(pdb, "db_delete_client_info");
2895
2896 db_err_msg* msg = NULL;
2897
2898 int status = db_delete_client_info_wlocked(pdb, pid, &msg);
2899
2901
2902 if (msg)
2903 db_flush_msg(&msg);
2904
2905 return status;
2906#else
2907 return DB_SUCCESS;
2908#endif
2909}
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 ( DATABASE pdb,
int  pid,
db_err_msg **  msg 
)
static

Definition at line 2844 of file odb.cxx.

2845{
2846 if (!pid)
2847 pid = ss_getpid();
2848
2849 int status = 0;
2850
2851 std::string str = msprintf("System/Clients/%0d", pid);
2852
2853 DATABASE_HEADER* pheader = pdb->database_header;
2854
2855 KEY* pkey = (KEY*)db_find_pkey_locked(pheader, NULL, str.c_str(), true, &status, msg);
2856 if (!pkey) {
2857 return status;
2858 }
2859
2860 status = db_set_mode_wlocked(pheader, pkey, MODE_READ | MODE_WRITE | MODE_DELETE, 2, msg);
2861 status = db_delete_key_locked(pdb, pkey, 0, msg);
2862 int32_t data = 0;
2863 db_set_value_wlocked(pdb, 0, "/System/Client Notify", &data, sizeof(data), 1, TID_INT32, msg);
2864
2865 return status;
2866}
#define TID_INT32
Definition midas.h:339
INT ss_getpid(void)
Definition system.cxx:1379
static int db_set_mode_wlocked(DATABASE_HEADER *, KEY *, WORD mode, int recurse, db_err_msg **)
Definition odb.cxx:7992
static int db_set_value_wlocked(DATABASE *pdb, KEY *pkey_root, const char *key_name, const void *data, INT data_size, INT num_values, DWORD type, db_err_msg **msg)
Definition odb.cxx:5068
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 2809 of file odb.cxx.

2810{
2811 DATABASE_CLIENT* pdbclient = &pheader->client[jclient];
2812
2813 /* decrement notify_count for open records and clear exclusive mode */
2814 int k;
2815 for (k = 0; k < pdbclient->max_index; k++)
2816 if (pdbclient->open_record[k].handle) {
2817 KEY* pkey = (KEY *) ((char *) pheader + pdbclient->open_record[k].handle);
2818 if (pkey->notify_count > 0)
2819 pkey->notify_count--;
2820
2821 if (pdbclient->open_record[k].access_mode & MODE_WRITE)
2822 db_set_mode_wlocked(pheader, pkey, (WORD) (pkey->access_mode & ~MODE_EXCLUSIVE), 2, msg);
2823 }
2824
2825 /* clear entry from client structure in buffer header */
2826 memset(pdbclient, 0, sizeof(DATABASE_CLIENT));
2827
2828 /* calculate new max_client_index entry */
2829 for (k = MAX_CLIENTS - 1; k >= 0; k--)
2830 if (pheader->client[k].pid != 0)
2831 break;
2832 pheader->max_client_index = k + 1;
2833
2834 /* count new number of clients */
2835 int nc;
2836 for (k = MAX_CLIENTS - 1, nc = 0; k >= 0; k--)
2837 if (pheader->client[k].pid != 0)
2838 nc++;
2839 pheader->num_clients = nc;
2840}
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() [1/2]

INT EXPRT db_delete_key ( HNDLE  hDB,
HNDLE  hKey 
)

Definition at line 3966 of file odb.cxx.

3967{
3968 if (rpc_is_remote())
3970
3971#ifdef LOCAL_ROUTINES
3972
3973 int status = DB_SUCCESS;
3974
3975 DATABASE* pdb = db_lock_database(hDB, &status, "db_delete_key");
3976
3977 if (!pdb)
3978 return status;
3979
3980 db_err_msg *msg = NULL;
3981
3982 const KEY* pkey = db_get_pkey(pdb->database_header, hKey, &status, "db_delete_key", &msg);
3983
3984 if (pkey) {
3985 status = db_delete_key_locked(pdb, pkey, 0, &msg);
3986 }
3987
3988 db_unlock_database(pdb, "db_delete_key");
3989
3990 if (msg)
3991 db_flush_msg(&msg);
3992
3993 return status;
3994#else
3995 return DB_SUCCESS;
3996#endif
3997}
#define RPC_DB_DELETE_KEY
Definition mrpc.h:63
Here is the call graph for this function:

◆ db_delete_key() [2/2]

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);
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 3933 of file odb.cxx.

3934{
3935 if (rpc_is_remote())
3937
3938#ifdef LOCAL_ROUTINES
3939
3940 int status = DB_SUCCESS;
3941
3942 DATABASE* pdb = db_lock_database(hDB, &status, "db_delete_key");
3943
3944 if (!pdb)
3945 return status;
3946
3947 db_err_msg *msg = NULL;
3948
3949 const KEY* pkey = db_get_pkey(pdb->database_header, hKey, &status, "db_delete_key", &msg);
3950
3951 if (pkey) {
3952 status = db_delete_key_locked(pdb, pkey, 0, &msg);
3953 }
3954
3955 db_unlock_database(pdb, "db_delete_key");
3956
3957 if (msg)
3958 db_flush_msg(&msg);
3959
3960 return status;
3961#else
3962 return DB_SUCCESS;
3963#endif
3964}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_delete_key_locked()

static int db_delete_key_locked ( DATABASE pdb,
const KEY pkey,
int  level,
db_err_msg **  msg 
)
static

Definition at line 3782 of file odb.cxx.

3783{
3784 INT status;
3785
3786 DATABASE_HEADER* pheader = pdb->database_header;
3787
3788 //printf("db_delete_key_locked: path \"%s\", level %d\n", db_get_path_pkey(pheader, pkey).c_str(), level);
3789
3790 /* check if someone has opened key or parent */
3791 if (level == 0) {
3792 status = db_check_open_record(pheader, pkey, msg);
3793 if (status != DB_SUCCESS) {
3794 return status;
3795 }
3796 }
3797
3798 bool deny_delete = false;
3799
3800 if (pkey->type == TID_KEY) { // delete contents of subdirectory
3801
3802 const KEY* pkey1 = db_enum_first_locked(pheader, pkey, msg);
3803
3804 while (pkey1) {
3805 const KEY* pkeynext = db_enum_next_locked(pheader, pkey, pkey1, msg);
3806
3807 status = db_delete_key_locked(pdb, pkey1, level + 1, msg);
3808
3809 if (status == DB_NO_ACCESS)
3810 deny_delete = true;
3811
3812 pkey1 = pkeynext;
3813 }
3814 }
3815
3816 HNDLE hKey = db_pkey_to_hkey(pheader, pkey);
3817
3818 /* return if key was already deleted by cyclic link */
3819
3820 if (pkey->parent_keylist == 0) {
3821 return DB_SUCCESS;
3822 }
3823
3824 /* do not delete the root */
3825
3826 if (hKey == pheader->root_key) {
3827 return DB_SUCCESS;
3828 }
3829
3830 /* check delete permission */
3831
3832 if (!(pkey->access_mode & MODE_DELETE) || deny_delete) {
3833 return DB_NO_ACCESS;
3834 }
3835
3836 /* check open record */
3837
3838#ifdef CHECK_OPEN_RECORD
3839 if (pkey->notify_count) {
3840 return DB_OPEN_RECORD;
3841 }
3842#endif
3843
3844 /* now delete key */
3845
3846 /* make ODB writable */
3847
3848 db_allow_write_locked(pdb, "db_delete_key_locked");
3849
3850 /* delete key data */
3851
3852 // FIXME: validate pkey->data and pkey->total_size.
3853
3854 if (pkey->type == TID_KEY) {
3855 free_key(pheader, (char *) pheader + pkey->data, pkey->total_size);
3856 } else {
3857 free_data(pheader, (char *) pheader + pkey->data, pkey->total_size, "db_delete_key_locked");
3858 }
3859
3860 /* unlink key from parent directory key list */
3861
3862 const KEY *pkey_parent = db_get_parent(pheader, pkey, &status, "db_delete_key_locked", msg);
3863
3864 const KEYLIST* pkeylist = db_get_pkeylist(pheader, pkey_parent, "db_delete_key_locked", msg);
3865
3866 if (pkeylist->first_key == hKey) {
3867 /* key is first in list */
3868 ((KEYLIST*)pkeylist)->first_key = pkey->next_key;
3869 } else {
3870 const KEY* pkey1 = db_enum_first_locked(pheader, pkey_parent, msg);
3871
3872 while (pkey1) {
3873 if (pkey1->next_key == hKey) {
3874 ((KEY*)pkey1)->next_key = pkey->next_key;
3875 break;
3876 }
3877
3878 pkey1 = db_enum_next_locked(pheader, pkey_parent, pkey1, msg);
3879 }
3880 }
3881
3882 ((KEYLIST*)pkeylist)->num_keys--;
3883
3884 /* poison deleted key */
3885
3886 KEY* wpkey = (KEY*)pkey;
3887
3888 wpkey->type = 9999;
3889 wpkey->num_values = 0;
3890 wpkey->data = 0;
3891 wpkey->total_size = 0;
3892 wpkey->item_size = 0;
3893 wpkey->next_key = 0;
3894 wpkey->parent_keylist = 0;
3895 wpkey->access_mode = 0;
3896 wpkey->notify_count = 0;
3897 wpkey->last_written = 0;
3898
3899 /* free key memory */
3900
3901 free_key(pheader, wpkey, sizeof(KEY));
3902
3903 return DB_SUCCESS;
3904}
static void free_key(DATABASE_HEADER *pheader, void *address, INT size)
Definition odb.cxx:345
static HNDLE db_pkey_to_hkey(const DATABASE_HEADER *pheader, const KEY *pkey)
Definition odb.cxx:1052
static int free_data(DATABASE_HEADER *pheader, void *address, INT size, const char *caller)
Definition odb.cxx:516
static int db_check_open_record(const DATABASE_HEADER *pheader, const KEY *pkey, db_err_msg **msg)
Definition odb.cxx:3758
INT last_written
Definition midas.h:1038
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_enum() [1/2]

INT EXPRT db_enum ( HNDLE  hDB,
HNDLE  hKeyRoot,
const char *  odb_path,
std::vector< HNDLE > *  sub_handles,
std::vector< KEY > *  sub_keys,
bool  follow_links 
)

Definition at line 5857 of file odb.cxx.

5878{
5879 if (rpc_is_remote()) {
5880 if (sub_handles)
5881 sub_handles->clear();
5882
5883 if (sub_keys)
5884 sub_keys->clear();
5885
5886 int status = 0;
5887
5888 if (follow_links)
5889 status = db_find_key(hDB, hKeyRoot, odb_path, &hKeyRoot);
5890 else
5891 status = db_find_link(hDB, hKeyRoot, odb_path, &hKeyRoot);
5892
5893 if (!hKeyRoot)
5894 return status;
5895
5896 for (int i=0 ; ; i++) {
5897 HNDLE hSubkey = 0;
5898
5899 if (follow_links)
5900 db_enum_key(hDB, hKeyRoot, i, &hSubkey);
5901 else
5902 db_enum_link(hDB, hKeyRoot, i, &hSubkey);
5903
5904 if (!hSubkey)
5905 break; // end of list reached
5906
5907 KEY subkey;
5908
5909 int status = db_get_key(hDB, hSubkey, &subkey);
5910
5911 if (status == DB_SUCCESS) {
5912 if (sub_handles)
5913 sub_handles->push_back(hSubkey);
5914 if (sub_keys)
5915 sub_keys->push_back(subkey);
5916 }
5917 }
5918
5919 return DB_SUCCESS;
5920 }
5921
5922#ifdef LOCAL_ROUTINES
5923
5924 if (sub_handles)
5925 sub_handles->clear();
5926
5927 if (sub_keys)
5928 sub_keys->clear();
5929
5930 int status = DB_SUCCESS;
5931
5932 DATABASE* pdb = db_lock_database(hDB, &status, "db_enum");
5933
5934 if (!pdb)
5935 return status;
5936
5937 db_err_msg *msg = NULL;
5938
5939 const KEY* pkeyroot = db_get_pkey(pdb->database_header, hKeyRoot, &status, "db_enum", &msg);
5940
5941 if (pkeyroot) {
5942 const KEY* pkey = db_find_pkey_locked(pdb->database_header, pkeyroot, odb_path, follow_links, &status, &msg);
5943 if (pkey)
5944 status = db_enum_locked(pdb->database_header, pkey, sub_handles, sub_keys, follow_links, &msg);
5945 }
5946
5947 db_unlock_database(pdb, "db_enum");
5948
5949 if (msg)
5950 db_flush_msg(&msg);
5951
5952 return status;
5953
5954#endif
5955
5956 return DB_SUCCESS;
5957}
INT db_enum_key(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
Definition odb.cxx:5357
static int db_enum_locked(const DATABASE_HEADER *pheader, const KEY *pkey, std::vector< HNDLE > *sub_handles, std::vector< KEY > *sub_keys, bool follow_links, db_err_msg **msg)
Definition odb.cxx:5707
Here is the call graph for this function:

◆ db_enum() [2/2]

INT EXPRT db_enum ( HNDLE  hDB,
HNDLE  hKeyRoot,
std::vector< HNDLE > *  sub_handles,
std::vector< KEY > *  sub_keys,
bool  follow_links 
)

Definition at line 5768 of file odb.cxx.

5788{
5789 if (rpc_is_remote()) {
5790 if (sub_handles)
5791 sub_handles->clear();
5792
5793 if (sub_keys)
5794 sub_keys->clear();
5795
5796 for (int i=0 ; ; i++) {
5797 HNDLE hSubkey = 0;
5798
5799 if (follow_links)
5800 db_enum_key(hDB, hKeyRoot, i, &hSubkey);
5801 else
5802 db_enum_link(hDB, hKeyRoot, i, &hSubkey);
5803
5804 if (!hSubkey)
5805 break; // end of list reached
5806
5807 KEY subkey;
5808
5809 int status = db_get_key(hDB, hSubkey, &subkey);
5810
5811 if (status == DB_SUCCESS) {
5812 if (sub_handles)
5813 sub_handles->push_back(hSubkey);
5814 if (sub_keys)
5815 sub_keys->push_back(subkey);
5816 }
5817 }
5818
5819 return DB_SUCCESS;
5820 }
5821
5822#ifdef LOCAL_ROUTINES
5823
5824 if (sub_handles)
5825 sub_handles->clear();
5826
5827 if (sub_keys)
5828 sub_keys->clear();
5829
5830 int status = DB_SUCCESS;
5831
5832 DATABASE* pdb = db_lock_database(hDB, &status, "db_enum");
5833
5834 if (!pdb)
5835 return status;
5836
5837 db_err_msg *msg = NULL;
5838
5839 const KEY* pkeyroot = db_get_pkey(pdb->database_header, hKeyRoot, &status, "db_enum", &msg);
5840
5841 if (pkeyroot) {
5842 status = db_enum_locked(pdb->database_header, pkeyroot, sub_handles, sub_keys, follow_links, &msg);
5843 }
5844
5845 db_unlock_database(pdb, "db_enum");
5846
5847 if (msg)
5848 db_flush_msg(&msg);
5849
5850 return status;
5851#endif
5852
5853 return DB_SUCCESS;
5854}
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 1083 of file odb.cxx.

1084{
1085 if (pkey->type != TID_KEY) {
1086 std::string path = db_get_path_pkey(pheader, pkey);
1087 db_msg(msg, MERROR, "db_enum_first_locked", "path \"%s\" tid %d is not a directory", path.c_str(), pkey->type);
1088 return NULL;
1089 }
1090
1091 const KEYLIST *pkeylist = db_get_pkeylist(pheader, pkey, "db_enum_first_locked", msg);
1092
1093 if (!pkeylist) {
1094 // error
1095 return NULL;
1096 }
1097
1098 if (pkeylist->num_keys == 0) {
1099 // empty directory
1100 return NULL;
1101 }
1102
1103 if (pkeylist->first_key == 0) {
1104 // empty directory
1105 return NULL;
1106 }
1107
1108 return db_get_pkey(pheader, pkeylist->first_key, NULL, "db_enum_first_locked", msg);
1109}
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);
}
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 5357 of file odb.cxx.

5358{
5359 if (rpc_is_remote())
5360 return rpc_call(RPC_DB_ENUM_KEY, hDB, hKey, idx, subkey_handle);
5361
5362#ifdef LOCAL_ROUTINES
5363 {
5364 DATABASE_HEADER *pheader;
5365 INT i;
5366 HNDLE parent;
5367
5368 if (hDB > _database_entries || hDB <= 0) {
5369 cm_msg(MERROR, "db_enum_key", "invalid database handle");
5370 return DB_INVALID_HANDLE;
5371 }
5372
5373 if (!_database[hDB - 1].attached) {
5374 cm_msg(MERROR, "db_enum_key", "invalid database handle");
5375 return DB_INVALID_HANDLE;
5376 }
5377
5378 *subkey_handle = 0;
5379
5380 /* first lock database */
5382
5383 pheader = _database[hDB - 1].database_header;
5384 if (!hKey)
5385 hKey = pheader->root_key;
5386
5387 /* check if hKey argument is correct */
5388 if (!db_validate_hkey(pheader, hKey)) {
5390 return DB_INVALID_HANDLE;
5391 }
5392
5393 db_err_msg *msg = NULL;
5394 int status;
5395
5396 const KEY* pkey = db_get_pkey(pheader, hKey, &status, "db_enum_key", &msg);
5397
5398 if (!pkey) {
5400 db_flush_msg(&msg);
5401 return DB_NO_MORE_SUBKEYS;
5402 }
5403
5404 if (pkey->type != TID_KEY) {
5406 return DB_NO_MORE_SUBKEYS;
5407 }
5408
5409 const KEYLIST* pkeylist = db_get_pkeylist(pheader, pkey, "db_enum_key", &msg);
5410
5411 if (!pkeylist) {
5413 db_flush_msg(&msg);
5414 return DB_NO_MORE_SUBKEYS;
5415 }
5416
5417 if (idx >= pkeylist->num_keys) {
5419 return DB_NO_MORE_SUBKEYS;
5420 }
5421
5422 pkey = db_get_pkey(pheader, pkeylist->first_key, &status, "db_enum_key", &msg);
5423
5424 if (!pkey) {
5425 std::string path = db_get_path_locked(pheader, hKey);
5426 HNDLE xfirst_key = pkeylist->first_key;
5428 if (msg)
5429 db_flush_msg(&msg);
5430 cm_msg(MERROR, "db_enum_key", "hkey %d path \"%s\" invalid first_key %d", hKey, path.c_str(), xfirst_key);
5431 return DB_NO_MORE_SUBKEYS;
5432 }
5433
5434 for (i = 0; i < idx; i++) {
5435 if (pkey->next_key == 0) {
5436 std::string path = db_get_path_locked(pheader, hKey);
5438 cm_msg(MERROR, "db_enum_key", "hkey %d path \"%s\" unexpected end of key list at index %d", hKey, path.c_str(), i);
5439 return DB_NO_MORE_SUBKEYS;
5440 }
5441
5442 pkey = db_get_pkey(pheader, pkey->next_key, &status, "db_enum_key", &msg);
5443
5444 if (!pkey) {
5445 std::string path = db_get_path_locked(pheader, hKey);
5447 db_flush_msg(&msg);
5448 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);
5449 return DB_NO_MORE_SUBKEYS;
5450 }
5451 }
5452
5453 /* resolve links */
5454 if (pkey->type == TID_LINK) {
5455 const char* str = (char *) pheader + pkey->data;
5456
5457 /* no not resolve if link to array index */
5458 if (strlen(str) > 0 && str[strlen(str) - 1] == ']') {
5459 *subkey_handle = (POINTER_T) pkey - (POINTER_T) pheader;
5461 return DB_SUCCESS;
5462 }
5463
5464 if (*str == '/') {
5465 /* absolute path */
5467 return db_find_key(hDB, 0, str, subkey_handle);
5468 } else {
5469 /* relative path */
5470 if (pkey->parent_keylist) {
5471 pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
5472 parent = pkeylist->parent;
5474 return db_find_key(hDB, parent, str, subkey_handle);
5475 } else {
5477 return db_find_key(hDB, 0, str, subkey_handle);
5478 }
5479 }
5480 }
5481
5482 *subkey_handle = (POINTER_T) pkey - (POINTER_T) pheader;
5484 }
5485#endif /* LOCAL_ROUTINES */
5486
5487 return DB_SUCCESS;
5488}
#define DB_NO_MORE_SUBKEYS
Definition midas.h:647
static bool db_validate_hkey(const DATABASE_HEADER *pheader, HNDLE hKey)
Definition odb.cxx:946
static std::string db_get_path_locked(const DATABASE_HEADER *pheader, HNDLE hKey)
Definition odb.cxx:4747
#define RPC_DB_ENUM_KEY
Definition mrpc.h:64
Here is the call 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 5495 of file odb.cxx.

5521{
5522 if (rpc_is_remote())
5523 return rpc_call(RPC_DB_ENUM_LINK, hDB, hKey, idx, subkey_handle);
5524
5525#ifdef LOCAL_ROUTINES
5526 {
5527 DATABASE_HEADER *pheader;
5528 KEYLIST *pkeylist;
5529 KEY *pkey;
5530 INT i;
5531
5532 if (hDB > _database_entries || hDB <= 0) {
5533 cm_msg(MERROR, "db_enum_link", "invalid database handle");
5534 return DB_INVALID_HANDLE;
5535 }
5536
5537 if (!_database[hDB - 1].attached) {
5538 cm_msg(MERROR, "db_enum_link", "invalid database handle");
5539 return DB_INVALID_HANDLE;
5540 }
5541
5542 *subkey_handle = 0;
5543
5544 /* first lock database */
5546
5547 pheader = _database[hDB - 1].database_header;
5548 if (!hKey)
5549 hKey = pheader->root_key;
5550
5551 /* check if hKey argument is correct */
5552 if (!db_validate_hkey(pheader, hKey)) {
5554 return DB_INVALID_HANDLE;
5555 }
5556
5557 pkey = (KEY *) ((char *) pheader + hKey);
5558
5559 if (pkey->type != TID_KEY) {
5561 return DB_NO_MORE_SUBKEYS;
5562 }
5563 pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
5564
5565 if (idx >= pkeylist->num_keys) {
5567 return DB_NO_MORE_SUBKEYS;
5568 }
5569
5570 // FIXME: validate pkeylist->first_key
5571 pkey = (KEY *) ((char *) pheader + pkeylist->first_key);
5572 for (i = 0; i < idx; i++) {
5573 // FIXME: validate pkey->next_key
5574 pkey = (KEY *) ((char *) pheader + pkey->next_key);
5575 }
5576
5577 *subkey_handle = (POINTER_T) pkey - (POINTER_T) pheader;
5579 }
5580#endif /* LOCAL_ROUTINES */
5581
5582 return DB_SUCCESS;
5583}
#define RPC_DB_ENUM_LINK
Definition mrpc.h:79
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_enum_locked()

static int db_enum_locked ( const DATABASE_HEADER pheader,
const KEY pkey,
std::vector< HNDLE > *  sub_handles,
std::vector< KEY > *  sub_keys,
bool  follow_links,
db_err_msg **  msg 
)
static

Definition at line 5707 of file odb.cxx.

5708{
5709 if (sub_handles)
5710 sub_handles->clear();
5711
5712 if (sub_keys)
5713 sub_keys->clear();
5714
5715 if (pkey->type != TID_KEY) {
5716 return DB_NO_MORE_SUBKEYS;
5717 }
5718
5719 const KEYLIST *pkeylist = db_get_pkeylist(pheader, pkey, "db_enum_locked", msg);
5720
5721 if (!pkeylist)
5722 return DB_CORRUPTED;
5723
5724 if (pkeylist->num_keys > 0) {
5725 HNDLE hsubkey = pkeylist->first_key;
5726
5727 while (hsubkey) {
5728 int status = 0;
5729 const KEY* psubkey = db_get_pkey(pheader, hsubkey, &status, "db_enum_locked", msg);
5730
5731 if (!psubkey)
5732 return status;
5733
5734 if (psubkey->type == TID_LINK && follow_links) {
5735 const KEY *plink = db_resolve_link_locked(pheader, psubkey, &status, msg);
5736
5737 if (plink) {
5738 HNDLE hlink = db_pkey_to_hkey(pheader, plink);
5739 if (sub_handles)
5740 sub_handles->push_back(hlink);
5741 if (sub_keys)
5742 sub_keys->push_back(*plink);
5743 } else {
5744 // link cannot be resolved
5745
5746 if (sub_handles)
5747 sub_handles->push_back(hsubkey);
5748 if (sub_keys)
5749 sub_keys->push_back(*psubkey);
5750 }
5751 } else {
5752 if (sub_handles)
5753 sub_handles->push_back(hsubkey);
5754 if (sub_keys)
5755 sub_keys->push_back(*psubkey);
5756 }
5757
5758 hsubkey = psubkey->next_key;
5759 }
5760 }
5761
5762 return DB_SUCCESS;
5763}
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 1111 of file odb.cxx.

1112{
1113 if (pkey->next_key == 0)
1114 return NULL;
1115
1116 return db_get_pkey(pheader, pkey->next_key, NULL, "db_enum_next_locked", msg);
1117}
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 4256 of file odb.cxx.

4257{
4258 if (rpc_is_remote())
4259 return rpc_call(RPC_DB_FIND_KEY, hDB, hKey, key_name, subhKey);
4260
4261#ifdef LOCAL_ROUTINES
4262 {
4263 if (subhKey)
4264 *subhKey = 0;
4265
4267
4268 DATABASE* pdb = db_lock_database(hDB, &status, "db_find_key");
4269
4270 if (!pdb)
4271 return status;
4272
4273 db_err_msg *msg = NULL;
4274
4275 status = db_find_key_locked(pdb->database_header, hKey, key_name, true, subhKey, &msg);
4276
4277 db_unlock_database(pdb, "db_find_key");
4278
4279 if (msg)
4280 db_flush_msg(&msg);
4281
4282 return status;
4283 }
4284#endif /* LOCAL_ROUTINES */
4285
4286 return DB_SUCCESS;
4287}
static INT db_find_key_locked(const DATABASE_HEADER *pheader, HNDLE hKey, const char *key_name, bool follow_links, HNDLE *subhKey, db_err_msg **msg)
Definition odb.cxx:4208
#define RPC_DB_FIND_KEY
Definition mrpc.h:60
Here is the call graph for this function:

◆ db_find_key_locked()

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

Definition at line 4208 of file odb.cxx.

4209{
4210 int status;
4211 const KEY* pkey = db_get_pkey(pheader, hKey, &status, "db_find_key", msg);
4212 if (!pkey) {
4213 if (subhKey)
4214 *subhKey = 0;
4215 return status;
4216 }
4217
4218 const KEY* plink = db_find_pkey_locked(pheader, pkey, key_name, follow_links, &status, msg);
4219
4220 if (!plink) {
4221 *subhKey = 0;
4222 return status;
4223 }
4224
4225 *subhKey = db_pkey_to_hkey(pheader, plink);
4226
4227 return DB_SUCCESS;
4228}
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,
const char *  odbpath,
std::vector< HNDLE > &  hKeyVector 
)

Definition at line 4352 of file odb.cxx.

4375{
4376 HNDLE hKey;
4377 INT status;
4378 char *pattern = NULL;
4379 char *subkeypath = NULL;
4380 char *parentkeypath = NULL;
4381 char localpath[MAX_ODB_PATH];
4382
4383 //make work on a local copy od odbpath to allow recursion
4384 mstrlcpy(localpath, odbpath, sizeof(localpath));
4385 parentkeypath = localpath;
4386
4387 //printf("localpath [%s]\n", localpath);
4388
4389 char *wildcard = strpbrk(localpath, "*?");
4390 if (wildcard) {
4391 //wildcard found
4392 subkeypath = strchr(wildcard, '/');
4393 if (subkeypath) {
4394 //truncate the string at slash
4395 *subkeypath = 0;
4396 subkeypath++;
4397 }
4398 parentkeypath = strrchr(localpath, '/');
4399 if (parentkeypath) {
4400 //truncate there too
4401 *parentkeypath = 0;
4402 pattern = parentkeypath+1;
4403 if((parentkeypath-1) == localpath){
4404 //path starts with '/', no parent path
4405 parentkeypath = NULL;
4406 } else {
4407 parentkeypath = localpath;
4408 }
4409 } else {
4410 //wildcard at top level, start with pattern
4411 pattern = localpath;
4412 parentkeypath = NULL;
4413 }
4414 }
4415
4416 //printf("pattern [%s]\n", pattern);
4417 //printf("parentkeypath [%s]\n", parentkeypath);
4418 //printf("subkeypath [%s]\n", subkeypath);
4419
4420 //if available search for parent key path
4421 if (parentkeypath) {
4422 status = db_find_key(hDB, hKeyRoot, parentkeypath, &hKey);
4423 if (status != DB_SUCCESS)
4424 return status;
4425 } else {
4426 hKey = hKeyRoot;
4427 }
4428
4429 //printf("hKeyRoot %d, hKey %d\n", hKeyRoot, hKey);
4430
4431 if (!pattern) {
4432 //no pattern: hKey matches!
4433 hKeyVector.push_back(hKey);
4434 return DB_SUCCESS;
4435 }
4436
4437 // try match all subkeys
4438
4439 for (int i=0 ; ; i++) {
4440 HNDLE hSubKey;
4441
4442 db_enum_key(hDB, hKey, i, &hSubKey);
4443
4444 if (!hSubKey)
4445 break; // end of list reached
4446
4447 KEY key;
4448
4449 status = db_get_key(hDB, hSubKey, &key);
4450
4451 if (status != DB_SUCCESS)
4452 continue;
4453
4454 bool match = strmatch(pattern, key.name);
4455
4456 //printf("match pattern [%s] name [%s] yields %d\n", pattern, key.name, match);
4457
4458 if (match) {
4459 if (!subkeypath) {
4460 //found
4461 hKeyVector.push_back(hSubKey);
4462 } else if (key.type == TID_KEY) {
4463 //recurse with hSubKey as root key and subkeypath as path
4464 db_find_keys(hDB, hSubKey, subkeypath, hKeyVector);
4465 }
4466 }
4467 }
4468
4469 if (hKeyVector.empty())
4470 return DB_NO_KEY;
4471
4472 return DB_SUCCESS;
4473}
BOOL strmatch(char *pattern, char *str)
Definition odb.cxx:3319
INT db_find_keys(HNDLE hDB, HNDLE hKeyRoot, const char *odbpath, std::vector< HNDLE > &hKeyVector)
Definition odb.cxx:4352
BOOL match(char *pat, char *str)
Definition odbedit.cxx:189
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 
)

dox

Definition at line 4293 of file odb.cxx.

4319{
4320 if (rpc_is_remote())
4321 return rpc_call(RPC_DB_FIND_LINK, hDB, hKey, key_name, subhKey);
4322
4323#ifdef LOCAL_ROUTINES
4324 {
4325 if (subhKey)
4326 *subhKey = 0;
4327
4329
4330 DATABASE* pdb = db_lock_database(hDB, &status, "db_find_link");
4331
4332 if (!pdb)
4333 return status;
4334
4335 db_err_msg *msg = NULL;
4336
4337 status = db_find_key_locked(pdb->database_header, hKey, key_name, false, subhKey, &msg);
4338
4339 db_unlock_database(pdb, "db_find_link");
4340
4341 if (msg)
4342 db_flush_msg(&msg);
4343
4344 return status;
4345 }
4346#endif /* LOCAL_ROUTINES */
4347
4348 return DB_SUCCESS;
4349}
#define RPC_DB_FIND_LINK
Definition mrpc.h:61
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 4871 of file odb.cxx.

4872{
4873 /* check if this key has notify count set */
4874 if (key->notify_count) {
4875
4877
4879
4880 std::string path = db_get_path_locked(pheader, hKey);
4881
4882 std::string line = msprintf("%s open %d times by", path.c_str(), key->notify_count);
4883
4884 //printf("path [%s] key.name [%s]\n", path, key->name);
4885
4886 int count = 0;
4887 for (int i = 0; i < pheader->max_client_index; i++) {
4888 DATABASE_CLIENT *pclient = &pheader->client[i];
4889 for (int j = 0; j < pclient->max_index; j++)
4890 if (pclient->open_record[j].handle == hKey) {
4891 count++;
4892 line += " \"";
4893 line += pclient->name;
4894 line += "\"";
4895 //sprintf(line + strlen(line), ", handle %d, mode %d ", pclient->open_record[j].handle, pclient->open_record[j].access_mode);
4896 }
4897 }
4898
4899 if (count < 1) {
4900 line += " a deleted client";
4901 }
4902
4903 line += "\n";
4904
4905 std::string *result = (std::string*)xresult;
4906 *result += line;
4907
4909 }
4910 return DB_SUCCESS;
4911}
double count
Definition mdump.cxx:33
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,
bool  follow_links,
int *  pstatus,
db_err_msg **  msg 
)
static

Definition at line 4042 of file odb.cxx.

4043{
4044 if (pkey == NULL) {
4045 pkey = db_get_pkey(pheader, pheader->root_key, pstatus, "db_find_key", msg);
4046 if (!pkey) {
4047 return NULL;
4048 }
4049 }
4050
4051 if (pkey->type != TID_KEY) {
4052 DWORD tid = pkey->type;
4053 std::string path = db_get_path_pkey(pheader, pkey);
4054 db_msg(msg, MERROR, "db_find_key", "Path \"%s\" tid %d is not a directory, looking for \"%s\"", path.c_str(), tid, key_name);
4055 if (pstatus)
4056 *pstatus = DB_NO_KEY;
4057 return NULL;
4058 }
4059
4060 if (key_name[0] == 0 || strcmp(key_name, "/") == 0) {
4061 if (!(pkey->access_mode & MODE_READ)) {
4062 if (pstatus)
4063 *pstatus = DB_NO_ACCESS;
4064 return NULL;
4065 }
4066 return pkey;
4067 }
4068
4069 const KEYLIST *pkeylist = db_get_pkeylist(pheader, pkey, "db_find_key", msg);
4070 if (!pkeylist) {
4071 if (pstatus)
4072 *pstatus = DB_CORRUPTED;
4073 return NULL;
4074 }
4075
4076 HNDLE hKey = db_pkey_to_hkey(pheader, pkey);
4077
4078 HNDLE last_good_hkey = hKey;
4079
4080 const char *pkey_name = key_name;
4081 do {
4082 assert(pkeylist!=NULL); // should never happen!
4083
4084 char str[MAX_ODB_PATH];
4085
4086 /* extract single subkey from key_name */
4087 pkey_name = extract_key(pkey_name, str, sizeof(str));
4088
4089 /* strip trailing '[n]' */
4090 if (strchr(str, '[') && str[strlen(str) - 1] == ']')
4091 *strchr(str, '[') = 0;
4092
4093 /* check if parent or current directory */
4094 if (strcmp(str, "..") == 0) {
4095 if (pkey->parent_keylist) {
4096 pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
4097 // FIXME: validate pkeylist->parent
4098 pkey = (KEY *) ((char *) pheader + pkeylist->parent);
4099 }
4100 continue;
4101 }
4102 if (strcmp(str, ".") == 0)
4103 continue;
4104
4105 last_good_hkey = hKey;
4106
4107 hKey = pkeylist->first_key;
4108
4109 if (hKey == 0) {
4110 // empty subdirectory
4111 if (pstatus)
4112 *pstatus = DB_NO_KEY;
4113 return NULL;
4114 }
4115
4116 int i;
4117 for (i = 0; i < pkeylist->num_keys; i++) {
4118 pkey = db_get_pkey(pheader, hKey, pstatus, "db_find_key", msg);
4119
4120 if (!pkey) {
4121 std::string path = db_get_path_locked(pheader, last_good_hkey);
4122 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);
4123 return NULL;
4124 }
4125
4126 if (!db_validate_key_offset(pheader, pkey->next_key)) {
4127 std::string path = db_get_path_locked(pheader, hKey);
4128 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);
4129 if (pstatus)
4130 *pstatus = DB_CORRUPTED;
4131 return NULL;
4132 }
4133
4134 if (equal_ustring(str, pkey->name))
4135 break;
4136
4137 if (pkey->next_key == 0) {
4138 if (pstatus)
4139 *pstatus = DB_NO_KEY;
4140 return NULL;
4141 }
4142
4143 hKey = pkey->next_key;
4144 }
4145
4146 if (i == pkeylist->num_keys) {
4147 if (pstatus)
4148 *pstatus = DB_NO_KEY;
4149 return NULL;
4150 }
4151
4152 /* resolve links */
4153 if (pkey->type == TID_LINK && follow_links) {
4154 /* copy destination, strip '/' */
4155 mstrlcpy(str, (char *) pheader + pkey->data, sizeof(str));
4156 if (str[strlen(str) - 1] == '/')
4157 str[strlen(str) - 1] = 0;
4158
4159 /* if link is pointer to array index, return link instead of destination */
4160 if (str[strlen(str) - 1] == ']')
4161 break;
4162
4163 /* append rest of key name if existing */
4164 if (pkey_name[0]) {
4165 mstrlcat(str, pkey_name, sizeof(str));
4166 return db_find_pkey_locked(pheader, NULL, str, follow_links, pstatus, msg);
4167 } else {
4168 /* if last key in chain is a link, return its destination */
4169 int status = 0;
4170 const KEY *plink = db_find_pkey_locked(pheader, NULL, str, follow_links, &status, msg);
4171 if (pstatus) {
4172 if (status == DB_NO_KEY)
4173 *pstatus = DB_INVALID_LINK;
4174 else
4175 *pstatus = status;
4176 }
4177 return plink;
4178 }
4179 }
4180
4181 /* key found: check if last in chain */
4182 if (*pkey_name == '/') {
4183 if (pkey->type != TID_KEY) {
4184 if (pstatus)
4185 *pstatus = DB_NO_KEY;
4186 return NULL;
4187 }
4188 }
4189
4190 if (pkey->type == TID_KEY) {
4191 /* descend one level */
4192 pkeylist = db_get_pkeylist(pheader, pkey, "db_find_key", msg);
4193
4194 if (!pkeylist) {
4195 if (pstatus)
4196 *pstatus = DB_CORRUPTED;
4197 return NULL;
4198 }
4199 } else {
4200 pkeylist = NULL;
4201 }
4202
4203 } while (*pkey_name == '/' && *(pkey_name + 1));
4204
4205 return pkey;
4206}
#define DB_INVALID_LINK
Definition midas.h:653
static bool db_validate_key_offset(const DATABASE_HEADER *pheader, int offset)
Definition odb.cxx:922
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 4913 of file odb.cxx.

4914{
4915 std::string *result = (std::string*)xresult;
4916
4917 /* check if this key has notify count set */
4918 if (key->notify_count) {
4921 db_allow_write_locked(&_database[hDB - 1], "db_fix_open_records");
4922
4923 int i;
4924 for (i = 0; i < pheader->max_client_index; i++) {
4925 DATABASE_CLIENT *pclient = &pheader->client[i];
4926 int j;
4927 for (j = 0; j < pclient->max_index; j++)
4928 if (pclient->open_record[j].handle == hKey)
4929 break;
4930 if (j < pclient->max_index)
4931 break;
4932 }
4933 if (i == pheader->max_client_index) {
4934 /* check if hKey argument is correct */
4935 if (!db_validate_hkey(pheader, hKey)) {
4937 return DB_SUCCESS;
4938 }
4939
4940 /* reset notify count */
4941 KEY *pkey = (KEY *) ((char *) pheader + hKey);
4942 pkey->notify_count = 0;
4943
4944 std::string path = db_get_path_locked(pheader, hKey);
4945 *result += path;
4946 *result += " fixed\n";
4947 }
4948
4950 }
4951 return DB_SUCCESS;
4952}
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 2306 of file odb.cxx.

2326{
2327 if (rpc_is_remote())
2329
2330#ifdef LOCAL_ROUTINES
2331 else {
2332 int status, size;
2333 uint32_t flush_period = 60;
2334 uint32_t last_flush = 0;
2335
2336 if (hDB > _database_entries || hDB <= 0) {
2337 cm_msg(MERROR, "db_flush_database", "invalid database handle");
2338 return DB_INVALID_HANDLE;
2339 }
2340
2341 /* create keys if not present */
2342 size = sizeof(flush_period);
2343 db_get_value(hDB, 0, "/System/Flush/Flush period", &flush_period, &size, TID_UINT32, true);
2344 size = sizeof(last_flush);
2345 db_get_value(hDB, 0, "/System/Flush/Last flush", &last_flush, &size, TID_UINT32, true);
2346
2347 HNDLE hkey;
2348 status = db_find_key(hDB, 0, "/System/Flush/Last flush", &hkey);
2349 if (status != DB_SUCCESS) {
2350 cm_msg(MERROR, "db_flush_database", "Cannot obtain key /System/Flush/Last flush");
2351 return DB_INVALID_HANDLE;
2352 }
2353
2355 DATABASE *pdb = &_database[hDB - 1];
2356 DATABASE_HEADER *pheader = pdb->database_header;
2357
2358 if (!_database[hDB - 1].attached) {
2360 cm_msg(MERROR, "db_flush_database", "invalid database handle");
2361 return DB_INVALID_HANDLE;
2362 }
2363
2364 db_err_msg *msg = nullptr;
2365
2366 const KEY *pkey = db_get_pkey(pheader, hkey, &status, "db_flush_database", &msg);
2367
2368 if (!pkey) {
2370 if (msg)
2371 db_flush_msg(&msg);
2372 return CM_NO_CLIENT;
2373 }
2374
2375 size = sizeof(last_flush);
2376 status = db_get_data_locked(pheader, pkey, 0, &last_flush, &size, TID_UINT32, &msg);
2377
2378 /* only flush if period has expired */
2379 if (ss_time() > last_flush + flush_period) {
2380 db_allow_write_locked(pdb, "db_flush_database");
2381
2382 /* update last flush time in ODB */
2383 last_flush = ss_time();
2384 db_set_value_wlocked(pdb, 0, "/System/Flush/Last flush", &last_flush, sizeof(last_flush), 1, TID_UINT32, &msg);
2385
2386 /* flush shared memory to disk */
2387 ss_shm_flush(pheader->name, _database[hDB - 1].shm_adr, _database[hDB - 1].shm_size, _database[hDB - 1].shm_handle, false);
2388 }
2389
2391 }
2392#endif /* LOCAL_ROUTINES */
2393
2394 return DB_SUCCESS;
2395}
#define TID_UINT32
Definition midas.h:337
DWORD ss_time()
Definition system.cxx:3534
INT db_get_value(HNDLE hDB, HNDLE hKeyRoot, const char *key_name, void *data, INT *buf_size, DWORD type, BOOL create)
Definition odb.cxx:5185
#define RPC_DB_FLUSH_DATABASE
Definition mrpc.h:85
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 193 of file odb.cxx.

194{
195 db_err_msg *msg = *msgp;
196 *msgp = NULL;
197
198 if (/* DISABLES CODE */ (0)) {
199 printf("db_flush_msg: %p\n", msg);
200 db_print_msg(msg);
201 }
202
203 while (msg != NULL) {
204 cm_msg(msg->message_type, msg->filename.c_str(), msg->line, msg->routine.c_str(), "%s", msg->text.c_str());
205 db_err_msg* next = msg->next;
206 msg->message_type = 0;
207 msg->next = NULL;
208 delete msg;
209 msg = next;
210 }
211}
static void static void db_print_msg(const db_err_msg *msg)
Definition odb.cxx:134
std::string routine
Definition odb.cxx:128
std::string filename
Definition odb.cxx:126
std::string text
Definition odb.cxx:129
db_err_msg * next
Definition odb.cxx:124
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 6563 of file odb.cxx.

6564{
6565 if (rpc_is_remote())
6566 return rpc_call(RPC_DB_GET_DATA, hDB, hKey, data, buf_size, type);
6567
6568#ifdef LOCAL_ROUTINES
6569 {
6570 int status;
6571
6572 if (hDB > _database_entries || hDB <= 0) {
6573 cm_msg(MERROR, "db_get_data", "Invalid database handle");
6574 return DB_INVALID_HANDLE;
6575 }
6576
6577 if (!_database[hDB - 1].attached) {
6578 cm_msg(MERROR, "db_get_data", "invalid database handle");
6579 return DB_INVALID_HANDLE;
6580 }
6581
6582 if (hKey < (int) sizeof(DATABASE_HEADER)) {
6583 cm_msg(MERROR, "db_get_data", "invalid key handle");
6584 return DB_INVALID_HANDLE;
6585 }
6586
6588
6590 db_err_msg* msg = NULL;
6591
6592 const KEY* pkey = db_get_pkey(pheader, hKey, &status, "db_get_data", &msg);
6593
6594 if (!pkey) {
6596 if (msg)
6597 db_flush_msg(&msg);
6598 return status;
6599 }
6600
6601 /* check for read access */
6602 if (!(pkey->access_mode & MODE_READ)) {
6604 if (msg)
6605 db_flush_msg(&msg);
6606 return DB_NO_ACCESS;
6607 }
6608
6609 /* follow links to array index */
6610 if (pkey->type == TID_LINK) {
6611 std::string link_name = (char *) pheader + pkey->data;
6612 if (link_name.length() > 0 && link_name.back() == ']') {
6613 size_t pos = link_name.rfind("[");
6614 if (pos == std::string::npos) {
6615 db_msg(&msg, MERROR, "db_get_data", "missing \"[\" in symlink to array element \"%s\" in \"%s\"", link_name.c_str(), db_get_path_pkey(pheader, pkey).c_str());
6617 if (msg)
6618 db_flush_msg(&msg);
6619 return DB_INVALID_LINK;
6620 }
6621 int idx = atoi(link_name.c_str()+pos+1);
6622 link_name.resize(pos);
6623 //printf("link name [%s] idx %d\n", link_name.c_str(), idx);
6624
6625 // relative symlinks did not work in the old db_get_data(), make sure they do not work now. K.O.
6626 if (link_name[0] != '/') {
6627 db_msg(&msg, MERROR, "db_get_data", "symlink \"%s\" should start with \"/\" in \"%s\"", link_name.c_str(), db_get_path_pkey(pheader, pkey).c_str());
6629 if (msg)
6630 db_flush_msg(&msg);
6631 return DB_INVALID_LINK;
6632 }
6633
6634 const KEY* pkey = db_find_pkey_locked(pheader, NULL, link_name.c_str(), true, &status, &msg);
6635
6636 if (!pkey) {
6638 if (msg)
6639 db_flush_msg(&msg);
6640 return status;
6641 }
6642
6643 //printf("db_get_data [%s] type [%s] idx %d\n", db_get_path_pkey(pheader, pkey).c_str(), rpc_tid_name(type), idx);
6644
6645 status = db_get_data_locked(pheader, pkey, idx, data, buf_size, type, &msg);
6646
6648 if (msg)
6649 db_flush_msg(&msg);
6650 return status;
6651 }
6652 }
6653
6654 //printf("db_get_data [%s] type [%s]\n", db_get_path_pkey(pheader, pkey).c_str(), rpc_tid_name(type));
6655
6656 status = db_get_data_locked(pheader, pkey, -1, data, buf_size, type, &msg);
6657
6659 if (msg)
6660 db_flush_msg(&msg);
6661
6662 return status;
6663 }
6664#endif /* LOCAL_ROUTINES */
6665
6666 return DB_SUCCESS;
6667}
#define RPC_DB_GET_DATA
Definition mrpc.h:66
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 6780 of file odb.cxx.

6805{
6806 if (rpc_is_remote())
6807 return rpc_call(RPC_DB_GET_DATA1, hDB, hKey, data, buf_size, type, num_values);
6808
6809#ifdef LOCAL_ROUTINES
6810 {
6811 DATABASE_HEADER *pheader;
6812 KEY *pkey;
6813
6814 if (hDB > _database_entries || hDB <= 0) {
6815 cm_msg(MERROR, "db_get_data", "Invalid database handle");
6816 return DB_INVALID_HANDLE;
6817 }
6818
6819 if (!_database[hDB - 1].attached) {
6820 cm_msg(MERROR, "db_get_data", "invalid database handle");
6821 return DB_INVALID_HANDLE;
6822 }
6823
6824 if (hKey < (int) sizeof(DATABASE_HEADER)) {
6825 cm_msg(MERROR, "db_get_data", "invalid key handle");
6826 return DB_INVALID_HANDLE;
6827 }
6828
6830
6831 pheader = _database[hDB - 1].database_header;
6832
6833 /* check if hKey argument is correct */
6834 if (!db_validate_hkey(pheader, hKey)) {
6836 return DB_INVALID_HANDLE;
6837 }
6838
6839 pkey = (KEY *) ((char *) pheader + hKey);
6840
6841 /* check for read access */
6842 if (!(pkey->access_mode & MODE_READ)) {
6844 return DB_NO_ACCESS;
6845 }
6846
6847 if (!pkey->type) {
6848 int pkey_type = pkey->type;
6850 cm_msg(MERROR, "db_get_data", "hkey %d invalid key type %d", hKey, pkey_type);
6851 return DB_INVALID_HANDLE;
6852 }
6853
6854 if (pkey->type != type) {
6855 int pkey_type = pkey->type;
6856 char pkey_name[NAME_LENGTH];
6857 mstrlcpy(pkey_name, pkey->name, sizeof(pkey_name));
6859 cm_msg(MERROR, "db_get_data", "\"%s\" is of type %s, not %s", pkey_name, rpc_tid_name(pkey_type), rpc_tid_name(type));
6860 return DB_TYPE_MISMATCH;
6861 }
6862
6863 /* keys cannot contain data */
6864 if (pkey->type == TID_KEY) {
6866 cm_msg(MERROR, "db_get_data", "Key cannot contain data");
6867 return DB_TYPE_MISMATCH;
6868 }
6869
6870 /* check if key has data */
6871 if (pkey->data == 0) {
6872 memset(data, 0, *buf_size);
6873 *buf_size = 0;
6875 return DB_SUCCESS;
6876 }
6877
6878 /* check if buffer is too small */
6879 if (pkey->num_values * pkey->item_size > *buf_size) {
6880 int pkey_size = pkey->num_values * pkey->item_size;
6881 memcpy(data, (char *) pheader + pkey->data, *buf_size);
6883 std::string path = db_get_path(hDB, hKey);
6884 cm_msg(MERROR, "db_get_data", "data for key \"%s\" truncated from %d to %d bytes", path.c_str(), pkey_size, *buf_size);
6885 return DB_TRUNCATED;
6886 }
6887
6888 /* copy key data */
6889 memcpy(data, (char *) pheader + pkey->data, pkey->num_values * pkey->item_size);
6890 *buf_size = pkey->num_values * pkey->item_size;
6891 *num_values = pkey->num_values;
6892
6894
6895 }
6896#endif /* LOCAL_ROUTINES */
6897
6898 return DB_SUCCESS;
6899}
#define RPC_DB_GET_DATA1
Definition mrpc.h:88
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 6917 of file odb.cxx.

6918{
6919 if (rpc_is_remote())
6920 return rpc_call(RPC_DB_GET_DATA_INDEX, hDB, hKey, data, buf_size, idx, type);
6921
6922#ifdef LOCAL_ROUTINES
6923 {
6924 DATABASE_HEADER *pheader;
6925 KEY *pkey;
6926
6927 if (hDB > _database_entries || hDB <= 0) {
6928 cm_msg(MERROR, "db_get_data", "Invalid database handle");
6929 return DB_INVALID_HANDLE;
6930 }
6931
6932 if (!_database[hDB - 1].attached) {
6933 cm_msg(MERROR, "db_get_data", "invalid database handle");
6934 return DB_INVALID_HANDLE;
6935 }
6936
6937 if (hKey < (int) sizeof(DATABASE_HEADER)) {
6938 cm_msg(MERROR, "db_get_data", "invalid key handle");
6939 return DB_INVALID_HANDLE;
6940 }
6941
6943
6944 pheader = _database[hDB - 1].database_header;
6945
6946 /* check if hKey argument is correct */
6947 if (!db_validate_hkey(pheader, hKey)) {
6949 return DB_INVALID_HANDLE;
6950 }
6951
6952 pkey = (KEY *) ((char *) pheader + hKey);
6953
6954 /* check for read access */
6955 if (!(pkey->access_mode & MODE_READ)) {
6957 return DB_NO_ACCESS;
6958 }
6959
6960 if (!pkey->type) {
6961 int pkey_type = pkey->type;
6963 cm_msg(MERROR, "db_get_data_index", "hkey %d invalid key type %d", hKey, pkey_type);
6964 return DB_INVALID_HANDLE;
6965 }
6966
6967 if (pkey->type != type) {
6968 int pkey_type = pkey->type;
6969 char pkey_name[NAME_LENGTH];
6970 mstrlcpy(pkey_name, pkey->name, sizeof(pkey_name));
6972 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));
6973 return DB_TYPE_MISMATCH;
6974 }
6975
6976 /* keys cannot contain data */
6977 if (pkey->type == TID_KEY) {
6979 cm_msg(MERROR, "db_get_data_index", "Key cannot contain data");
6980 return DB_TYPE_MISMATCH;
6981 }
6982
6983 /* check if key has data */
6984 if (pkey->data == 0) {
6985 memset(data, 0, *buf_size);
6986 *buf_size = 0;
6988 return DB_SUCCESS;
6989 }
6990
6991 /* check if index in range */
6992 if (idx < 0 || idx >= pkey->num_values) {
6993 int pkey_num_values = pkey->num_values;
6994 memset(data, 0, *buf_size);
6996
6997 std::string path = db_get_path(hDB, hKey);
6998 cm_msg(MERROR, "db_get_data_index", "index (%d) exceeds array length (%d) for key \"%s\"", idx, pkey_num_values, path.c_str());
6999 return DB_OUT_OF_RANGE;
7000 }
7001
7002 /* check if buffer is too small */
7003 if (pkey->item_size > *buf_size) {
7004 int pkey_size = pkey->item_size;
7005 /* copy data */
7006 memcpy(data, (char *) pheader + pkey->data + idx * pkey->item_size, *buf_size);
7008 std::string path = db_get_path(hDB, hKey);
7009 cm_msg(MERROR, "db_get_data_index", "data for key \"%s\" truncated from %d to %d bytes", path.c_str(), pkey_size, *buf_size);
7010 return DB_TRUNCATED;
7011 }
7012
7013 /* copy key data */
7014 memcpy(data, (char *) pheader + pkey->data + idx * pkey->item_size, pkey->item_size);
7015 *buf_size = pkey->item_size;
7016
7018
7019 }
7020#endif /* LOCAL_ROUTINES */
7021
7022 return DB_SUCCESS;
7023}
#define DB_OUT_OF_RANGE
Definition midas.h:652
#define RPC_DB_GET_DATA_INDEX
Definition mrpc.h:82
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 5277 of file odb.cxx.

5278{
5279 /* check for correct type */
5280 if (pkey->type != (type)) {
5281 db_msg(msg, MERROR, "db_get_data_locked", "odb entry \"%s\" is of type %s, not %s", db_get_path_pkey(pheader, pkey).c_str(), rpc_tid_name(pkey->type), rpc_tid_name(type));
5282 return DB_TYPE_MISMATCH;
5283 }
5284
5285 /* check for correct type */
5286 if (pkey->type == TID_KEY) {
5287 db_msg(msg, MERROR, "db_get_data_locked", "odb entry \"%s\" is of type %s, cannot contain data", db_get_path_pkey(pheader, pkey).c_str(), rpc_tid_name(pkey->type));
5288 return DB_TYPE_MISMATCH;
5289 }
5290
5291 /* check for read access */
5292 if (!(pkey->access_mode & MODE_READ)) {
5293 db_msg(msg, MERROR, "db_get_data_locked", "odb entry \"%s\" has no read access", db_get_path_pkey(pheader, pkey).c_str());
5294 return DB_NO_ACCESS;
5295 }
5296
5297 /* check if buffer is too small */
5298 if ((idx == -1 && pkey->num_values * pkey->item_size > *buf_size) || (idx != -1 && pkey->item_size > *buf_size)) {
5299 memcpy(data, (char *) pheader + pkey->data, *buf_size);
5300 db_msg(msg, MERROR, "db_get_data_locked", "odb entry \"%s\" data truncated, size is %d (%d*%d), buffer size is only %d", db_get_path_pkey(pheader, pkey).c_str(), pkey->num_values * pkey->item_size, pkey->num_values, pkey->item_size, *buf_size);
5301 return DB_TRUNCATED;
5302 }
5303
5304 /* check if index in boundaries */
5305 if (idx != -1 && idx >= pkey->num_values) {
5306 cm_msg(MERROR, "db_get_data_locked", "odb entry \"%s\" index %d is out of valid range 0..%d", db_get_path_pkey(pheader, pkey).c_str(), idx, pkey->num_values-1);
5307 return DB_INVALID_PARAM;
5308 }
5309
5310 /* copy key data */
5311 if (idx == -1) {
5312 memcpy(data, (char *) pheader + pkey->data, pkey->num_values * pkey->item_size);
5313 *buf_size = pkey->num_values * pkey->item_size;
5314 } else {
5315 memcpy(data, (char *) pheader + pkey->data + idx * pkey->item_size, pkey->item_size);
5316 *buf_size = pkey->item_size;
5317 }
5318
5319 return DB_SUCCESS;
5320}
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 811 of file odb.cxx.

812{
813 *data_size = 0;
814 *key_size = 0;
815
816 int status = 0;
817
818 DATABASE* pdb = db_lock_database(hDB, &status, "db_get_free_mem");
819
820 if (!pdb)
821 return status;
822
823 const DATABASE_HEADER* pheader = pdb->database_header;
824
825 const FREE_DESCRIP *pfree = (const FREE_DESCRIP *) ((char *) pheader + pheader->first_free_key);
826
827 while ((POINTER_T) pfree != (POINTER_T) pheader) {
828 *key_size += pfree->size;
829 pfree = (const FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
830 }
831
832 *data_size = 0;
833
834 pfree = (const FREE_DESCRIP *) ((char *) pheader + pheader->first_free_data);
835
836 while ((POINTER_T) pfree != (POINTER_T) pheader) {
837 *data_size += pfree->size;
838 pfree = (const FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
839 }
840
841 db_unlock_database(pdb, "db_get_free_mem");
842
843 return DB_SUCCESS;
844}
INT first_free_data
Definition msystem.h:441
INT next_free
Definition msystem.h:407
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 6043 of file odb.cxx.

6044{
6045 if (rpc_is_remote())
6046 return rpc_call(RPC_DB_GET_KEY, hDB, hKey, key);
6047
6048#ifdef LOCAL_ROUTINES
6049 {
6050 DATABASE_HEADER *pheader;
6051 int status;
6052
6053 if (hDB > _database_entries || hDB <= 0) {
6054 cm_msg(MERROR, "db_get_key", "invalid database handle");
6055 return DB_INVALID_HANDLE;
6056 }
6057
6058 if (!_database[hDB - 1].attached) {
6059 cm_msg(MERROR, "db_get_key", "invalid database handle");
6060 return DB_INVALID_HANDLE;
6061 }
6062
6063 if (hKey < (int) sizeof(DATABASE_HEADER) && hKey != 0) {
6064 cm_msg(MERROR, "db_get_key", "invalid key handle");
6065 return DB_INVALID_HANDLE;
6066 }
6067
6068 db_err_msg *msg = NULL;
6069
6071
6072 pheader = _database[hDB - 1].database_header;
6073
6074 status = db_get_key_locked(pheader, hKey, key, &msg);
6075
6077
6078 if (msg)
6079 db_flush_msg(&msg);
6080
6081 return status;
6082 }
6083#endif /* LOCAL_ROUTINES */
6084
6085 return DB_SUCCESS;
6086}
static INT db_get_key_locked(const DATABASE_HEADER *pheader, HNDLE hKey, KEY *key, db_err_msg **msg)
Definition odb.cxx:5966
#define RPC_DB_GET_KEY
Definition mrpc.h:65
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 6215 of file odb.cxx.

6216{
6217 if (rpc_is_remote())
6218 return rpc_call(RPC_DB_GET_KEY_INFO, hDB, hKey, name, name_size, type, num_values, item_size);
6219
6220#ifdef LOCAL_ROUTINES
6221 {
6222 DATABASE_HEADER *pheader;
6223 KEY *pkey;
6224 KEYLIST *pkeylist;
6225
6226 if (hDB > _database_entries || hDB <= 0) {
6227 cm_msg(MERROR, "db_get_key_info", "invalid database handle");
6228 return DB_INVALID_HANDLE;
6229 }
6230
6231 if (!_database[hDB - 1].attached) {
6232 cm_msg(MERROR, "db_get_key_info", "invalid database handle");
6233 return DB_INVALID_HANDLE;
6234 }
6235
6236 if (hKey < (int) sizeof(DATABASE_HEADER)) {
6237 cm_msg(MERROR, "db_get_key_info", "invalid key handle");
6238 return DB_INVALID_HANDLE;
6239 }
6240
6242
6243 pheader = _database[hDB - 1].database_header;
6244
6245 /* check if hKey argument is correct */
6246 if (!db_validate_hkey(pheader, hKey)) {
6248 return DB_INVALID_HANDLE;
6249 }
6250
6251 pkey = (KEY *) ((char *) pheader + hKey);
6252
6253 if ((INT) strlen(pkey->name) + 1 > name_size) {
6254 /* truncate name */
6255 memcpy(name, pkey->name, name_size - 1);
6256 name[name_size] = 0;
6257 } else
6258 strcpy(name, pkey->name);
6259
6260 /* convert "root" to "/" */
6261 if (strcmp(name, "root") == 0)
6262 strcpy(name, "/");
6263
6264 *type = pkey->type;
6265 *num_values = pkey->num_values;
6266 *item_size = pkey->item_size;
6267
6268 if (pkey->type == TID_KEY) {
6269 pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
6270 *num_values = pkeylist->num_keys;
6271 }
6272
6274 }
6275#endif /* LOCAL_ROUTINES */
6276
6277 return DB_SUCCESS;
6278}
#define RPC_DB_GET_KEY_INFO
Definition mrpc.h:87
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 5966 of file odb.cxx.

5967{
5968 if (!hKey)
5969 hKey = pheader->root_key;
5970
5971 /* check if hKey argument is correct */
5972 if (!db_validate_hkey(pheader, hKey)) {
5973 return DB_INVALID_HANDLE;
5974 }
5975
5976 const KEY* pkey = (const KEY *) ((char *) pheader + hKey);
5977
5978 if (pkey->type < 1 || pkey->type >= TID_LAST) {
5979 int pkey_type = pkey->type;
5980 db_msg(msg, MERROR, "db_get_key", "hkey %d invalid key type %d", hKey, pkey_type);
5981 return DB_INVALID_HANDLE;
5982 }
5983
5984 /* check for link to array index */
5985 if (pkey->type == TID_LINK) {
5986 char link_name[MAX_ODB_PATH];
5987 mstrlcpy(link_name, (char *) pheader + pkey->data, sizeof(link_name));
5988 if (strlen(link_name) > 0 && link_name[strlen(link_name) - 1] == ']') {
5989 if (strchr(link_name, '[') == NULL)
5990 return DB_INVALID_LINK;
5991
5992 HNDLE hkeylink;
5993 if (db_find_key_locked(pheader, 0, link_name, true, &hkeylink, msg) != DB_SUCCESS)
5994 return DB_INVALID_LINK;
5995 int status = db_get_key_locked(pheader, hkeylink, key, msg);
5996 key->num_values = 1; // fake number of values
5997 return status;
5998 }
5999 }
6000
6001 memcpy(key, pkey, sizeof(KEY));
6002
6003 return DB_SUCCESS;
6004}
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 6156 of file odb.cxx.

6157{
6158 if (rpc_is_remote())
6159 return rpc_call(RPC_DB_GET_KEY_TIME, hDB, hKey, delta);
6160
6161#ifdef LOCAL_ROUTINES
6162 {
6163 DATABASE_HEADER *pheader;
6164 KEY *pkey;
6165
6166 if (hDB > _database_entries || hDB <= 0) {
6167 cm_msg(MERROR, "db_get_key", "invalid database handle");
6168 return DB_INVALID_HANDLE;
6169 }
6170
6171 if (!_database[hDB - 1].attached) {
6172 cm_msg(MERROR, "db_get_key", "invalid database handle");
6173 return DB_INVALID_HANDLE;
6174 }
6175
6176 if (hKey < (int) sizeof(DATABASE_HEADER)) {
6177 cm_msg(MERROR, "db_get_key", "invalid key handle");
6178 return DB_INVALID_HANDLE;
6179 }
6180
6182
6183 pheader = _database[hDB - 1].database_header;
6184
6185 /* check if hKey argument is correct */
6186 if (!db_validate_hkey(pheader, hKey)) {
6188 return DB_INVALID_HANDLE;
6189 }
6190
6191 pkey = (KEY *) ((char *) pheader + hKey);
6192
6193 *delta = ss_time() - pkey->last_written;
6194
6196
6197 }
6198#endif /* LOCAL_ROUTINES */
6199
6200 return DB_SUCCESS;
6201}
#define RPC_DB_GET_KEY_TIME
Definition mrpc.h:83
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 6096 of file odb.cxx.

6097{
6098 if (rpc_is_remote())
6099 return rpc_call(RPC_DB_GET_LINK, hDB, hKey, key);
6100
6101#ifdef LOCAL_ROUTINES
6102 {
6103 DATABASE_HEADER *pheader;
6104
6105 if (hDB > _database_entries || hDB <= 0) {
6106 cm_msg(MERROR, "db_get_link", "invalid database handle");
6107 return DB_INVALID_HANDLE;
6108 }
6109
6110 if (!_database[hDB - 1].attached) {
6111 cm_msg(MERROR, "db_get_link", "invalid database handle");
6112 return DB_INVALID_HANDLE;
6113 }
6114
6115 if (hKey < (int) sizeof(DATABASE_HEADER) && hKey != 0) {
6116 cm_msg(MERROR, "db_get_link", "invalid key handle");
6117 return DB_INVALID_HANDLE;
6118 }
6119
6120 db_err_msg *msg = NULL;
6121
6123
6124 pheader = _database[hDB - 1].database_header;
6125
6126 int status = DB_SUCCESS;
6127
6128 const KEY* pkey = db_get_pkey(pheader, hKey, &status, "db_get_link", &msg);
6129 if (pkey) {
6130 memcpy(key, pkey, sizeof(KEY));
6131 } else {
6132 memset(key, 0, sizeof(KEY));
6133 //abort();
6134 }
6135
6137
6138 if (msg)
6139 db_flush_msg(&msg);
6140
6141 return status;
6142 }
6143#endif /* LOCAL_ROUTINES */
6144
6145 return DB_SUCCESS;
6146}
#define RPC_DB_GET_LINK
Definition mrpc.h:92
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 6680 of file odb.cxx.

6681{
6682 if (rpc_is_remote())
6683 return rpc_call(RPC_DB_GET_LINK_DATA, hDB, hKey, data, buf_size, type);
6684
6685#ifdef LOCAL_ROUTINES
6686 {
6687 DATABASE_HEADER *pheader;
6688 KEY *pkey;
6689
6690 if (hDB > _database_entries || hDB <= 0) {
6691 cm_msg(MERROR, "db_get_data", "Invalid database handle");
6692 return DB_INVALID_HANDLE;
6693 }
6694
6695 if (!_database[hDB - 1].attached) {
6696 cm_msg(MERROR, "db_get_data", "invalid database handle");
6697 return DB_INVALID_HANDLE;
6698 }
6699
6700 if (hKey < (int) sizeof(DATABASE_HEADER)) {
6701 cm_msg(MERROR, "db_get_data", "invalid key handle");
6702 return DB_INVALID_HANDLE;
6703 }
6704
6706
6707 pheader = _database[hDB - 1].database_header;
6708
6709 /* check if hKey argument is correct */
6710 if (!db_validate_hkey(pheader, hKey)) {
6712 return DB_INVALID_HANDLE;
6713 }
6714
6715 pkey = (KEY *) ((char *) pheader + hKey);
6716
6717 /* check for read access */
6718 if (!(pkey->access_mode & MODE_READ)) {
6720 return DB_NO_ACCESS;
6721 }
6722
6723 if (!pkey->type) {
6724 int pkey_type = pkey->type;
6726 cm_msg(MERROR, "db_get_data", "hkey %d invalid key type %d", hKey, pkey_type);
6727 return DB_INVALID_HANDLE;
6728 }
6729
6730 if (pkey->type != type) {
6731 int pkey_type = pkey->type;
6732 char pkey_name[NAME_LENGTH];
6733 mstrlcpy(pkey_name, pkey->name, sizeof(pkey_name));
6735 cm_msg(MERROR, "db_get_data", "\"%s\" is of type %s, not %s", pkey_name, rpc_tid_name(pkey_type), rpc_tid_name(type));
6736 return DB_TYPE_MISMATCH;
6737 }
6738
6739 /* keys cannot contain data */
6740 if (pkey->type == TID_KEY) {
6742 cm_msg(MERROR, "db_get_data", "Key cannot contain data");
6743 return DB_TYPE_MISMATCH;
6744 }
6745
6746 /* check if key has data */
6747 if (pkey->data == 0) {
6748 memset(data, 0, *buf_size);
6749 *buf_size = 0;
6751 return DB_SUCCESS;
6752 }
6753
6754 /* check if buffer is too small */
6755 if (pkey->num_values * pkey->item_size > *buf_size) {
6756 int pkey_size = pkey->num_values * pkey->item_size;
6757 memcpy(data, (char *) pheader + pkey->data, *buf_size);
6759 std::string path = db_get_path(hDB, hKey);
6760 cm_msg(MERROR, "db_get_data", "data for key \"%s\" truncated from %d to %d bytes", path.c_str(), pkey_size, *buf_size);
6761 return DB_TRUNCATED;
6762 }
6763
6764 /* copy key data */
6765 memcpy(data, (char *) pheader + pkey->data, pkey->num_values * pkey->item_size);
6766 *buf_size = pkey->num_values * pkey->item_size;
6767
6769
6770 }
6771#endif /* LOCAL_ROUTINES */
6772
6773 return DB_SUCCESS;
6774}
#define RPC_DB_GET_LINK_DATA
Definition mrpc.h:93
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 1398 of file odb.cxx.

1399{
1400 assert(pdb);
1401 assert(pdb->database_header);
1402
1403 DATABASE_HEADER *pheader = pdb->database_header;
1404
1405 int idx = pdb->client_index;
1406
1407 if (idx < 0 || idx >= pheader->max_client_index || idx >= MAX_CLIENTS) {
1408 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);
1410 abort();
1411 }
1412
1413 DATABASE_CLIENT* pclient = &pheader->client[idx]; // safe to dereference on "idx"
1414
1415 if (pclient->name[0] == 0) {
1416 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);
1418 abort();
1419 }
1420
1421 int pid = getpid();
1422
1423 if (pclient->pid != pid) {
1424 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);
1426 abort();
1427 }
1428
1429 //printf("db_get_my_client_locked: idx %d, name [%s], pid %d\n", idx, pclient->name, pid);
1430
1431 //if (strcmp(pclient->name, "mdump") == 0) {
1432 // ss_semaphore_release(pdb->semaphore);
1433 // for (int i=0; i<15; i++) {
1434 // printf("sleep %d\n", i);
1435 // ::sleep(1);
1436 // }
1437 // abort();
1438 //}
1439
1440 return pclient;
1441}
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 5586 of file odb.cxx.

5608{
5609 if (rpc_is_remote())
5610 return rpc_call(RPC_DB_GET_NEXT_LINK, hDB, hKey, subkey_handle);
5611
5612#ifdef LOCAL_ROUTINES
5613 {
5614 DATABASE_HEADER *pheader;
5615 KEYLIST *pkeylist;
5616 KEY *pkey;
5617 INT descent;
5618
5619 if (hDB > _database_entries || hDB <= 0) {
5620 cm_msg(MERROR, "db_enum_link", "invalid database handle");
5621 return DB_INVALID_HANDLE;
5622 }
5623
5624 if (!_database[hDB - 1].attached) {
5625 cm_msg(MERROR, "db_enum_link", "invalid database handle");
5626 return DB_INVALID_HANDLE;
5627 }
5628
5629 *subkey_handle = 0;
5630
5631 /* first lock database */
5633
5634 pheader = _database[hDB - 1].database_header;
5635 if (!hKey)
5636 hKey = pheader->root_key;
5637
5638 /* check if hKey argument is correct */
5639 if (!db_validate_hkey(pheader, hKey)) {
5641 return DB_INVALID_HANDLE;
5642 }
5643
5644 pkey = (KEY *) ((char *) pheader + hKey);
5645
5646 descent = TRUE;
5647 do {
5648 if (pkey->type != TID_KEY || !descent) {
5649 if (pkey->next_key) {
5650 /* key has next key, return it */
5651 // FIXME: validate pkey->next_key
5652 pkey = (KEY *) ((char *) pheader + pkey->next_key);
5653
5654 if (pkey->type != TID_KEY) {
5655 *subkey_handle = (POINTER_T) pkey - (POINTER_T) pheader;
5657 return DB_SUCCESS;
5658 }
5659
5660 /* key has subkeys, so descent on the next iteration */
5661 descent = TRUE;
5662 } else {
5663 if (pkey->parent_keylist == 0) {
5664 /* return if we are back to the root key */
5666 return DB_NO_MORE_SUBKEYS;
5667 }
5668
5669 /* key is last in list, traverse up */
5670 pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
5671
5672 // FIXME: validate pkeylist->parent
5673 pkey = (KEY *) ((char *) pheader + pkeylist->parent);
5674 descent = FALSE;
5675 }
5676 } else {
5677 if (descent) {
5678 /* find first subkey */
5679 pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
5680
5681 if (pkeylist->num_keys == 0) {
5682 /* if key has no subkeys, look for next key on this level */
5683 descent = FALSE;
5684 } else {
5685 /* get first subkey */
5686 // FIXME: validate pkeylist->first_key
5687 pkey = (KEY *) ((char *) pheader + pkeylist->first_key);
5688
5689 if (pkey->type != TID_KEY) {
5690 *subkey_handle = (POINTER_T) pkey - (POINTER_T) pheader;
5692 return DB_SUCCESS;
5693 }
5694 }
5695 }
5696 }
5697
5698 } while (TRUE);
5699 }
5700#endif /* LOCAL_ROUTINES */
5701
5702 return DB_SUCCESS;
5703}
#define RPC_DB_GET_NEXT_LINK
Definition mrpc.h:91
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 4955 of file odb.cxx.

4977{
4978 str[0] = 0;
4979
4980 if (rpc_is_remote())
4981 return rpc_call(RPC_DB_GET_OPEN_RECORDS, hDB, hKey, str, buf_size);
4982
4983 std::string result;
4984
4985#ifdef LOCAL_ROUTINES
4986
4987 if (fix)
4988 db_scan_tree(hDB, hKey, 0, db_fix_open_records, &result); // FIXME: should use db_scan_tree_wlocked()
4989 else
4990 db_scan_tree(hDB, hKey, 0, db_find_open_records, &result); // FIXME: should use db_scan_tree_locked()
4991
4992#endif
4993
4994 mstrlcpy(str, result.c_str(), buf_size);
4995
4996 return DB_SUCCESS;
4997}
INT db_scan_tree(HNDLE hDB, HNDLE hKey, INT level, INT(*callback)(HNDLE, HNDLE, KEY *, INT, void *), void *info)
Definition odb.cxx:4544
static int db_fix_open_records(HNDLE hDB, HNDLE hKey, KEY *key, INT level, void *xresult)
Definition odb.cxx:4913
static int db_find_open_records(HNDLE hDB, HNDLE hKey, KEY *key, INT level, void *xresult)
Definition odb.cxx:4871
#define RPC_DB_GET_OPEN_RECORDS
Definition mrpc.h:84
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 1057 of file odb.cxx.

1058{
1059 if (pkey->parent_keylist == 0) {
1060 // they asked for the parent of "/", return "/"
1061 return db_get_pkey(pheader, pheader->root_key, pstatus, caller, msg);
1062 }
1063
1064 if (!db_validate_data_offset(pheader, pkey->parent_keylist)) {
1065 db_msg(msg, MERROR, caller, "hkey %d path \"%s\" invalid pkey->parent %d", db_pkey_to_hkey(pheader, pkey), db_get_path_pkey(pheader, pkey).c_str(), pkey->parent_keylist);
1066 if (pstatus)
1067 *pstatus = DB_CORRUPTED;
1068 return NULL;
1069 }
1070
1071 const KEYLIST *pkeylist = (const KEYLIST *) ((char *) pheader + pkey->parent_keylist);
1072
1073 if (pkeylist->first_key == 0 && pkeylist->num_keys != 0) {
1074 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_pkey(pheader, pkey).c_str(), pkeylist->first_key, pkeylist->num_keys);
1075 if (pstatus)
1076 *pstatus = DB_CORRUPTED;
1077 return NULL;
1078 }
1079
1080 return db_get_pkey(pheader, pkeylist->parent, pstatus, caller, msg);
1081}
static bool db_validate_data_offset(const DATABASE_HEADER *pheader, int offset)
Definition odb.cxx:934
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 4476 of file odb.cxx.

4494{
4495 if (rpc_is_remote())
4496 return rpc_call(RPC_DB_GET_PARENT, hDB, hKey, parenthKey);
4497
4498#ifdef LOCAL_ROUTINES
4499 {
4500
4501 DATABASE_HEADER *pheader;
4502 const KEY *pkey;
4503
4504 if (hDB > _database_entries || hDB <= 0) {
4505 cm_msg(MERROR, "db_get_parent", "invalid database handle");
4506 return DB_INVALID_HANDLE;
4507 }
4508
4509 if (!_database[hDB - 1].attached) {
4510 cm_msg(MERROR, "db_get_parent", "invalid database handle");
4511 return DB_INVALID_HANDLE;
4512 }
4513
4514 if (hKey < (int) sizeof(DATABASE_HEADER)) {
4515 cm_msg(MERROR, "db_get_parent", "invalid key handle");
4516 return DB_INVALID_HANDLE;
4517 }
4518
4520
4521 pheader = _database[hDB - 1].database_header;
4522 pkey = (const KEY *) ((char *) pheader + hKey);
4523
4524 /* find parent key */
4525 const KEYLIST *pkeylist = (const KEYLIST *) ((char *) pheader + pkey->parent_keylist);
4526
4527 if (!db_validate_hkey(pheader, pkeylist->parent)) {
4529 return DB_INVALID_HANDLE;
4530 }
4531
4532 pkey = (const KEY *) ((char *) pheader + pkeylist->parent);
4533
4534 *parenthKey = (POINTER_T) pkey - (POINTER_T) pheader;
4535
4537 }
4538#endif
4539
4540 return DB_SUCCESS;
4541}
#define RPC_DB_GET_PARENT
Definition mrpc.h:98
Here is the call graph for this function:

◆ db_get_path() [1/2]

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

Definition at line 4825 of file odb.cxx.

4839{
4840 if (rpc_is_remote()) {
4841 char path[MAX_ODB_PATH];
4842 int status = rpc_call(RPC_DB_GET_PATH, hDB, hKey, path, sizeof(path));
4843 if (status != DB_SUCCESS) {
4844 return msprintf("(RPC_DB_GET_PATH status %d)", status);
4845 }
4846 return path;
4847 }
4848
4849#ifdef LOCAL_ROUTINES
4850 {
4851 int status = DB_SUCCESS;
4852
4853 DATABASE* pdb = db_lock_database(hDB, &status, "db_get_path");
4854
4855 if (!pdb)
4856 return "(CANNOT LOCK ODB)";
4857
4858 std::string xpath = db_get_path_locked(pdb->database_header, hKey);
4859
4860 db_unlock_database(pdb, "db_get_path");
4861
4862 return xpath;
4863 }
4864#endif /* LOCAL_ROUTINES */
4865
4866 return "(no LOCAL_ROUTINES)";
4867}
#define RPC_DB_GET_PATH
Definition mrpc.h:62
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 4775 of file odb.cxx.

4798{
4799 if (rpc_is_remote())
4800 return rpc_call(RPC_DB_GET_PATH, hDB, hKey, path, buf_size);
4801
4802#ifdef LOCAL_ROUTINES
4803 {
4804 int status = 0;
4805
4806 DATABASE* pdb = db_lock_database(hDB, &status, "db_get_path");
4807
4808 if (!pdb)
4809 return status;
4810
4811 std::string xpath = db_get_path_locked(pdb->database_header, hKey);
4812
4813 db_unlock_database(pdb, "db_get_path");
4814
4815 mstrlcpy(path, xpath.c_str(), buf_size);
4816
4817 return DB_SUCCESS;
4818 }
4819#endif /* LOCAL_ROUTINES */
4820
4821 return DB_SUCCESS;
4822}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_path_locked()

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

Definition at line 4747 of file odb.cxx.

4748{
4749 //printf("db_get_path_locked: hkey %d\n", hKey);
4750
4751 if (!hKey)
4752 hKey = pheader->root_key;
4753
4754 if (hKey == pheader->root_key) {
4755 return "/";
4756 }
4757
4758 /* check if hKey argument is correct */
4759 if (hKey == 0) {
4760 return "(ZERO_HKEY)";
4761 }
4762
4763 /* check if hKey argument is correct */
4764 if (!db_validate_key_offset(pheader, hKey)) {
4765 return "(INVALID_HKEY)";
4766 }
4767
4768 const KEY* pkey = (const KEY *) ((char *) pheader + hKey);
4769
4770 return db_get_path_pkey(pheader, pkey);
4771}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_path_pkey()

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

Definition at line 4682 of file odb.cxx.

4683{
4684 std::string path = "";
4685 int level = 0;
4686 while (1) {
4687 //printf("db_get_path_pkey: hkey %d, pkey name \"%s\", type %d, parent %d, path \"%s\"\n", hKey, pkey->name, pkey->type, pkey->parent_keylist, path.c_str());
4688
4689 /* check key type */
4690 if (pkey->type <= 0 || pkey->type >= TID_LAST) {
4691 std::string xpath = msprintf("(INVALID_KEY_TYPE_%d)", pkey->type);;
4692 if (path.length() > 0) {
4693 xpath += "/";
4694 xpath += path;
4695 }
4696 return xpath;
4697 }
4698
4699 /* add key name in front of path */
4700 std::string str = path;
4701 path = "";
4702 if (pkey->name[0] == 0) {
4703 path += "(EMPTY_NAME)";
4704 } else {
4705 path += pkey->name;
4706 }
4707 if (str.length() > 0)
4708 path += "/";
4709 path += str;
4710
4711 if (!pkey->parent_keylist) {
4712 return path;
4713 }
4714
4715 if (!db_validate_data_offset(pheader, pkey->parent_keylist)) {
4716 return "(INVALID_PARENT_KEYLIST)/" + path;
4717 }
4718
4719 /* find parent key */
4720 const KEYLIST* pkeylist = (const KEYLIST *) ((char *) pheader + pkey->parent_keylist);
4721
4722 if (pkeylist->parent == pheader->root_key) {
4723 return "/" + path;
4724 }
4725
4726 if (pkeylist->parent == 0) {
4727 return "(NULL_PARENT)/" + path;
4728 }
4729
4730 if (!db_validate_key_offset(pheader, pkeylist->parent)) {
4731 return "(INVALID_PARENT)/" + path;
4732 }
4733
4734 pkey = (const KEY *) ((char *) pheader + pkeylist->parent);
4735
4736 level ++;
4737
4738 if (level >= MAX_ODB_PATH) {
4739 return "(TRUNCATED)/" + path;
4740 }
4741 };
4742
4743 /* NOT REACHED */
4744}
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 959 of file odb.cxx.

960{
961 BOOL hKey_is_root_key = FALSE;
962
963 if (!hKey) {
964 hKey_is_root_key = TRUE;
965 hKey = pheader->root_key;
966 }
967
968 /* check if hKey argument is correct */
969 if (hKey == 0) {
970 if (pstatus)
971 *pstatus = DB_INVALID_HANDLE;
972 return NULL;
973 }
974
975 /* check if hKey argument is correct */
976 if (!db_validate_key_offset(pheader, hKey)) {
977 if (pstatus)
978 *pstatus = DB_INVALID_HANDLE;
979 return NULL;
980 }
981
982 const KEY* pkey = (const KEY *) ((char *) pheader + hKey);
983
984 if (pkey->type < 1 || pkey->type >= TID_LAST) {
985 DWORD tid = pkey->type;
986 if (hKey_is_root_key) {
987 db_msg(msg, MERROR, caller, "db_get_pkey: root_key hkey %d invalid key type %d, database root directory is corrupted", hKey, tid);
988 if (pstatus)
989 *pstatus = DB_CORRUPTED;
990 return NULL;
991 } else {
992 std::string path = db_get_path_pkey(pheader, pkey);
993 db_msg(msg, MERROR, caller, "db_get_pkey: hkey %d path \"%s\" invalid key type %d", hKey, path.c_str(), tid);
994 }
995 if (pstatus)
996 *pstatus = DB_NO_KEY;
997 return NULL;
998 }
999
1000 if (pkey->name[0] == 0) {
1001 std::string path = db_get_path_pkey(pheader, pkey);
1002 db_msg(msg, MERROR, caller, "db_get_pkey: hkey %d path \"%s\" invalid name \"%s\" is empty", hKey, path.c_str(), pkey->name);
1003 if (pstatus)
1004 *pstatus = DB_NO_KEY;
1005 return NULL;
1006 }
1007
1008 return pkey;
1009}
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,
const KEY pkey,
const char *  caller,
db_err_msg **  msg,
bool  kludge_repair = false 
)
static

Definition at line 1011 of file odb.cxx.

1012{
1013 if (pkey->type != TID_KEY) {
1014 std::string path = db_get_path_pkey(pheader, pkey);
1015 db_msg(msg, MERROR, caller, "db_get_pkeylist: path \"%s\" unexpected call to db_get_pkeylist(), not a subdirectory, pkey->type %d", path.c_str(), pkey->type);
1016 return NULL;
1017 }
1018
1019 if (!db_validate_data_offset(pheader, pkey->data)) {
1020 std::string path = db_get_path_pkey(pheader, pkey);
1021 db_msg(msg, MERROR, caller, "Invalid pkey->data %d at path \"%s\"", pkey->data, path.c_str());
1022 return NULL;
1023 }
1024
1025 const KEYLIST *pkeylist = (const KEYLIST *) ((char *) pheader + pkey->data);
1026
1027 if (pkeylist->parent != db_pkey_to_hkey(pheader, pkey)) {
1028 std::string path = db_get_path_pkey(pheader, pkey);
1029 db_msg(msg, MERROR, caller, "Invalid pkeylist->parent %d should be hkey %d at \"%s\"", pkeylist->parent, db_pkey_to_hkey(pheader, pkey), path.c_str());
1030 return NULL;
1031 }
1032
1033 if (pkeylist->first_key == 0 && pkeylist->num_keys != 0) {
1034 if (!kludge_repair) {
1035 std::string path = db_get_path_pkey(pheader, pkey);
1036 db_msg(msg, MERROR, caller, "Invalid pkeylist->first_key %d should be non zero for num_keys %d at \"%s\"", pkeylist->first_key, pkeylist->num_keys, path.c_str());
1037 return NULL;
1038 }
1039
1040 // FIXME: this repair should be done in db_validate_and_repair_key()
1041
1042 // FIXME: this will crash if ODB is write-protected.
1043
1044 std::string path = db_get_path_pkey(pheader, pkey);
1045 db_msg(msg, MERROR, caller, "Repaired invalid num_keys %d when pkeylist->first_key is zero at \"%s\"", pkeylist->num_keys, path.c_str());
1046 ((KEYLIST*)pkeylist)->num_keys = 0;
1047 }
1048
1049 return pkeylist;
1050}
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:11736
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 11736 of file odb.cxx.

11737{
11738 if (rpc_is_remote()) {
11739 align = ss_get_struct_align();
11740 return rpc_call(RPC_DB_GET_RECORD, hDB, hKey, data, buf_size, align);
11741 }
11742#ifdef LOCAL_ROUTINES
11743 {
11744 KEY key;
11745 INT convert_flags, status;
11746 INT total_size;
11747 void *pdata;
11748
11749 if (data && buf_size) {
11750 memset(data, 0x00, *buf_size);
11751 }
11752
11753 convert_flags = 0;
11754
11755 if (!align)
11756 align = ss_get_struct_align();
11757 else {
11758 /* only convert data if called remotely, as indicated by align != 0 */
11759 if (rpc_is_mserver()) {
11760 convert_flags = rpc_get_convert_flags();
11761 }
11762 }
11763
11764 /* check if key has subkeys */
11766 if (status != DB_SUCCESS)
11767 return status;
11768
11769 if (key.type != TID_KEY) {
11770 /* copy single key */
11771 if (key.item_size * key.num_values != *buf_size) {
11772 cm_msg(MERROR, "db_get_record", "struct size mismatch for \"%s\" (expected size: %d, size in ODB: %d * %d = %d)",
11775 }
11776
11777 db_get_data(hDB, hKey, data, buf_size, key.type);
11778
11779 if (convert_flags) {
11780 if (key.num_values > 1)
11782 else
11783 rpc_convert_single(data, key.type, RPC_OUTGOING, convert_flags);
11784 }
11785
11786 return DB_SUCCESS;
11787 }
11788
11789 /* check record size */
11790 db_get_record_size(hDB, hKey, align, &total_size);
11791 if (total_size != *buf_size) {
11792 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);
11794 }
11795
11796 /* get subkey data */
11797 pdata = data;
11798 total_size = 0;
11799
11800 db_err_msg* msg = NULL;
11802 DATABASE *pdb = &_database[hDB - 1];
11803 db_recurse_record_tree_locked(pdb, hKey, &pdata, &total_size, align, NULL, FALSE, convert_flags, &msg);
11805 if (msg)
11806 db_flush_msg(&msg);
11807
11808 //if (total_size != *buf_size) {
11809 // 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);
11810 // //return DB_STRUCT_SIZE_MISMATCH;
11811 //}
11812 }
11813#endif /* LOCAL_ROUTINES */
11814
11815 return DB_SUCCESS;
11816}
#define DB_STRUCT_SIZE_MISMATCH
Definition midas.h:650
INT ss_get_struct_align()
Definition system.cxx:1321
INT db_get_record_size(HNDLE hDB, HNDLE hKey, INT align, INT *buf_size)
Definition odb.cxx:11640
static void db_recurse_record_tree_locked(const DATABASE *pdb, const KEY *pkey, void **data, INT *total_size, INT base_align, INT *max_align, BOOL bSet, INT convert_flags, db_err_msg **msg)
Definition odb.cxx:11461
void rpc_convert_data(void *data, INT tid, INT flags, INT total_size, INT convert_flags)
Definition midas.cxx:11837
bool rpc_is_mserver(void)
Definition midas.cxx:12949
INT rpc_get_convert_flags(void)
Definition midas.cxx:13161
void rpc_convert_single(void *data, INT tid, INT flags, INT convert_flags)
Definition midas.cxx:11812
#define RPC_DB_GET_RECORD
Definition mrpc.h:71
#define RPC_OUTGOING
Definition midas.h:1584
#define RPC_FIXARRAY
Definition midas.h:1582
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 11834 of file odb.cxx.

11835{
11836 int size = *buf_size;
11837 int odb_size = 0;
11838 int status;
11839 //char path[MAX_ODB_PATH];
11840
11841 /* check record size first */
11842
11844 if (status != DB_SUCCESS)
11845 return status;
11846
11847 /* if size mismatch, call repair function */
11848
11849 if (odb_size != size) {
11850 std::string path = db_get_path(hDB, hKey);
11851 cm_msg(MINFO, "db_get_record1", "Fixing ODB \"%s\" struct size mismatch (expected %d, odb size %d)", path.c_str(), size, odb_size);
11852 status = db_create_record(hDB, hKey, "", rec_str);
11853 if (status != DB_SUCCESS)
11854 return status;
11855 }
11856
11857 /* run db_get_record(), if success, we are done */
11858
11859 status = db_get_record(hDB, hKey, data, buf_size, align);
11860 if (status == DB_SUCCESS)
11861 return status;
11862
11863 /* try repair with db_check_record() */
11864
11865 status = db_check_record(hDB, hKey, "", rec_str, TRUE);
11866 if (status != DB_SUCCESS)
11867 return status;
11868
11869 /* verify struct size again, because there can still be a mismatch if there
11870 * are extra odb entries at the end of the record as db_check_record()
11871 * seems to ignore all odb entries past the end of "rec_str". K.O.
11872 */
11873
11875 if (status != DB_SUCCESS)
11876 return status;
11877
11878 std::string path = db_get_path(hDB, hKey);
11879
11880 if (odb_size != size) {
11881 cm_msg(MERROR, "db_get_record1", "after db_check_record() still struct size mismatch (expected %d, odb size %d) of \"%s\", calling db_create_record()", size, odb_size, path.c_str());
11882 status = db_create_record(hDB, hKey, "", rec_str);
11883 if (status != DB_SUCCESS)
11884 return status;
11885 }
11886
11887 cm_msg(MERROR, "db_get_record1", "repaired struct size mismatch of \"%s\"", path.c_str());
11888
11889 *buf_size = size;
11890 status = db_get_record(hDB, hKey, data, buf_size, align);
11891
11892 return status;
11893}
INT db_check_record(HNDLE hDB, HNDLE hKey, const char *keyname, const char *rec_str, BOOL correct)
Definition odb.cxx:13003
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:12197
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 12197 of file odb.cxx.

12198{
12199 int status = DB_SUCCESS;
12200
12201 printf("db_get_record2!\n");
12202
12203 assert(data != NULL);
12204 assert(xbuf_size != NULL);
12205 assert(*xbuf_size > 0);
12206 assert(correct == 0);
12207
12208 int truncated = 0;
12209#if 1
12210 char* r1 = NULL;
12211 int rs = *xbuf_size;
12212 if (1) {
12213 r1 = (char*)malloc(rs);
12214 assert(r1 != NULL);
12215 memset(data, 0xFF, *xbuf_size);
12216 memset(r1, 0xFF, rs);
12217 //status = db_get_record1(hDB, hKey, r1, &rs, 0, rec_str);
12218 status = db_get_record(hDB, hKey, r1, &rs, 0);
12219 printf("db_get_record status %d\n", status);
12220 }
12221#endif
12222
12223 char* buf_start = (char*)data;
12224 int buf_size = *xbuf_size;
12225
12226 char* buf_ptr = buf_start;
12227 int buf_remain = buf_size;
12228
12229 while (rec_str && *rec_str != 0) {
12230 char title[256];
12231 char key_name[MAX_ODB_PATH];
12232 int tid = 0;
12233 int n_data = 0;
12234 int string_length = 0;
12235 const char* rec_str_next = NULL;
12236
12237 status = db_parse_record(rec_str, &rec_str_next, title, sizeof(title), key_name, sizeof(key_name), &tid, &n_data, &string_length);
12238
12239 //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);
12240
12241 rec_str = rec_str_next;
12242
12243 if (status != DB_SUCCESS) {
12244 return status;
12245 }
12246
12247 if (key_name[0] == 0) {
12248 // skip title strings, comments, etc
12249 continue;
12250 }
12251
12252 status = db_get_record2_read_element(hDB, hKey, key_name, tid, n_data, string_length, buf_start, &buf_ptr, &buf_remain, correct);
12253 if (status == DB_INVALID_PARAM) {
12254 cm_msg(MERROR, "db_get_record2", "error: cannot continue reading odb record because of previous fatal error, status %d", status);
12255 return DB_INVALID_PARAM;
12256 } if (status != DB_SUCCESS) {
12257 truncated = 1;
12258 }
12259
12260 rec_str = rec_str_next;
12261 }
12262
12263 if (r1) {
12264 int ok = -1;
12265 int i;
12266 for (i=0; i<rs; i++) {
12267 if (r1[i] != buf_start[i]) {
12268 ok = i;
12269 break;
12270 }
12271 }
12272 if (ok>=0 || buf_remain>0) {
12273 printf("db_get_record2: miscompare at %d out of %d, buf_remain %d\n", ok, rs, buf_remain);
12274 } else {
12275 printf("db_get_record2: check ok\n");
12276 }
12277 }
12278
12279 if (buf_remain > 0) {
12280 // FIXME: we finished processing the data definition string, but unused space remains in the buffer
12281 return DB_TRUNCATED;
12282 }
12283
12284 if (truncated)
12285 return DB_TRUNCATED;
12286 else
12287 return DB_SUCCESS;
12288}
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:12078
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:11895
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 12078 of file odb.cxx.

12079{
12080 assert(tid > 0);
12081 assert(n_data > 0);
12082 int tsize = rpc_tid_size(tid);
12083 int offset = *buf_ptr - buf_start;
12084 int align = 0;
12085 if (tsize && (offset%tsize != 0)) {
12086 while (offset%tsize != 0) {
12087 align++;
12088 *(*buf_ptr) = 0xFF; // pad bytes for correct data alignement
12089 (*buf_ptr)++;
12090 (*buf_remain)--;
12091 offset++;
12092 }
12093 }
12094 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);
12095 if (tsize > 0) {
12096 int xsize = tsize*n_data;
12097 if (xsize > *buf_remain) {
12098 cm_msg(MERROR, "db_get_record2", "buffer overrun at key \"%s\", size %d, buffer remaining %d", key_name, xsize, *buf_remain);
12099 return DB_INVALID_PARAM;
12100 }
12101 int ysize = xsize;
12102 int status = db_get_value(hDB, hKey, key_name, *buf_ptr, &ysize, tid, FALSE);
12103 //printf("status %d, xsize %d\n", status, xsize);
12104 if (status != DB_SUCCESS) {
12105 cm_msg(MERROR, "db_get_record2", "cannot read \"%s\", db_get_value() status %d", key_name, status);
12106 memset(*buf_ptr, 0, xsize);
12107 *buf_ptr += xsize;
12108 *buf_remain -= xsize;
12109 return status;
12110 }
12111 *buf_ptr += xsize;
12112 *buf_remain -= xsize;
12113 } else if (tid == TID_STRING) {
12114 int xstatus = 0;
12115 int i;
12116 for (i=0; i<n_data; i++) {
12117 int xsize = string_length;
12118 if (xsize > *buf_remain) {
12119 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);
12120 return DB_INVALID_PARAM;
12121 }
12122 std::string xkey_name = msprintf("%s[%d]", key_name, i);
12123 int status = db_get_value(hDB, hKey, xkey_name.c_str(), *buf_ptr, &xsize, tid, FALSE);
12124 //printf("status %d, string length %d, xsize %d, actual len %d\n", status, string_length, xsize, (int)strlen(*buf_ptr));
12125 if (status == DB_TRUNCATED) {
12126 // make sure string is NUL terminated
12127 (*buf_ptr)[string_length-1] = 0;
12128 cm_msg(MERROR, "db_get_record2", "string key \"%s\" index %d, string value was truncated", key_name, i);
12129 } else if (status != DB_SUCCESS) {
12130 cm_msg(MERROR, "db_get_record2", "cannot read string \"%s\"[%d], db_get_value() status %d", key_name, i, status);
12131 memset(*buf_ptr, 0, string_length);
12132 xstatus = status;
12133 }
12134 *buf_ptr += string_length;
12135 *buf_remain -= string_length;
12136 }
12137 if (xstatus != 0) {
12138 return xstatus;
12139 }
12140 } else {
12141 cm_msg(MERROR, "db_get_record2", "cannot read key \"%s\" of unsupported type %d", key_name, tid);
12142 return DB_INVALID_PARAM;
12143 }
12144 return DB_SUCCESS;
12145}
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 11640 of file odb.cxx.

11641{
11642 if (rpc_is_remote()) {
11643 align = ss_get_struct_align();
11644 return rpc_call(RPC_DB_GET_RECORD_SIZE, hDB, hKey, align, buf_size);
11645 }
11646#ifdef LOCAL_ROUTINES
11647 {
11648 KEY key;
11649 INT status, max_align;
11650
11651 if (!align)
11652 align = ss_get_struct_align();
11653
11654 /* check if key has subkeys */
11656 if (status != DB_SUCCESS)
11657 return status;
11658
11659 if (key.type != TID_KEY) {
11660 /* just a single key */
11661 *buf_size = key.item_size * key.num_values;
11662 return DB_SUCCESS;
11663 }
11664
11665 db_err_msg* msg = NULL;
11667
11668 DATABASE *pdb = &_database[hDB - 1];
11669
11670 /* determine record size */
11671 *buf_size = max_align = 0;
11672 db_recurse_record_tree_locked(pdb, hKey, NULL, buf_size, align, &max_align, 0, 0, &msg);
11673
11674 //int tmp = *buf_size;
11675 /* correct for byte padding */
11676 *buf_size = VALIGN(*buf_size, max_align);
11677
11678 //if (tmp != *buf_size) {
11679 // 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);
11680 //}
11681
11683 if (msg)
11684 db_flush_msg(&msg);
11685 }
11686#endif /* LOCAL_ROUTINES */
11687
11688 return DB_SUCCESS;
11689}
#define VALIGN(adr, align)
Definition midas.h:526
#define RPC_DB_GET_RECORD_SIZE
Definition mrpc.h:70
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 5185 of file odb.cxx.

5186{
5187 if (rpc_is_remote())
5188 return rpc_call(RPC_DB_GET_VALUE, hDB, hKeyRoot, key_name, data, buf_size, type, create);
5189
5190#ifdef LOCAL_ROUTINES
5191 {
5192 INT status;
5193
5194 if (hDB > _database_entries || hDB <= 0) {
5195 cm_msg(MERROR, "db_get_value", "invalid database handle %d", hDB);
5196 return DB_INVALID_HANDLE;
5197 }
5198
5199 if (!_database[hDB - 1].attached) {
5200 cm_msg(MERROR, "db_get_value", "invalid database handle %d", hDB);
5201 return DB_INVALID_HANDLE;
5202 }
5203
5204 /* check if key name contains index */
5205 char keyname[MAX_ODB_PATH];
5206 mstrlcpy(keyname, key_name, sizeof(keyname));
5207 int idx = -1;
5208 if (strchr(keyname, '[') && strchr(keyname, ']')) {
5209 char* p;
5210 for (p = strchr(keyname, '[') + 1; *p && *p != ']'; p++)
5211 if (!isdigit(*p))
5212 break;
5213
5214 if (*p && *p == ']') {
5215 idx = atoi(strchr(keyname, '[') + 1);
5216 *strchr(keyname, '[') = 0;
5217 }
5218 }
5219
5220 /* now lock database */
5222
5223 DATABASE* pdb = &_database[hDB - 1];
5224 DATABASE_HEADER* pheader = pdb->database_header;
5225 db_err_msg* msg = NULL;
5226
5227 const KEY* pkey_root = db_get_pkey(pheader, hKeyRoot, &status, "db_get_value", &msg);
5228
5229 if (!pkey_root) {
5231 if (msg)
5232 db_flush_msg(&msg);
5233 return status;
5234 }
5235
5236 const KEY* pkey = db_find_pkey_locked(pheader, pkey_root, keyname, true, &status, &msg);
5237
5238 if (!pkey) {
5239 if (create) {
5240 db_allow_write_locked(&_database[hDB-1], "db_get_value");
5241 /* set default value if key was created */
5242
5243 /* get string size from data size */
5244 int size;
5245 if (type == TID_STRING || type == TID_LINK)
5246 size = *buf_size;
5247 else
5248 size = rpc_tid_size(type);
5249
5250 status = db_set_value_wlocked(pdb, (KEY*)pkey_root, keyname, data, *buf_size, *buf_size / size, type, &msg);
5252 if (msg)
5253 db_flush_msg(&msg);
5254 return status;
5255 } else {
5257 if (msg)
5258 db_flush_msg(&msg);
5259 return DB_NO_KEY;
5260 }
5261 }
5262
5263 status = db_get_data_locked(pheader, pkey, idx, data, buf_size, type, &msg);
5264
5266 if (msg)
5267 db_flush_msg(&msg);
5268
5269 return status;
5270 }
5271#endif /* LOCAL_ROUTINES */
5272
5273 return DB_SUCCESS;
5274}
#define RPC_DB_GET_VALUE
Definition mrpc.h:59
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 13967 of file odb.cxx.

13968{
13969 int status;
13970 int hkey;
13971
13972 //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);
13973
13974 if (index > 0 && create) {
13975 cm_msg(MERROR, "db_get_value_string", "cannot resize odb string arrays, please use db_resize_string() instead");
13976 return DB_OUT_OF_RANGE;
13977 }
13978
13979 status = db_find_key(hdb, hKeyRoot, key_name, &hkey);
13980 if (status == DB_SUCCESS) {
13981 KEY key;
13982 status = db_get_key(hdb, hkey, &key);
13983 if (status != DB_SUCCESS)
13984 return status;
13985 if (index < 0 || index >= key.num_values)
13986 return DB_OUT_OF_RANGE;
13987 int size = key.item_size;
13988 if (size == 0) {
13989 if (s)
13990 *s = "";
13991 //printf("db_get_value_string: return empty string, item_size %d\n", key.item_size);
13992 return DB_SUCCESS;
13993 }
13994 char* buf = (char*)malloc(size);
13995 assert(buf != NULL);
13996 status = db_get_data_index(hdb, hkey, buf, &size, index, TID_STRING);
13997 if (status != DB_SUCCESS) {
13998 free(buf);
13999 return status;
14000 }
14001 if (s)
14002 *s = buf;
14003 free(buf);
14004 //printf("db_get_value_string: return [%s], len %d, item_size %d, size %d\n", s->c_str(), s->length(), key.item_size, size);
14005 return DB_SUCCESS;
14006 } else if (!create) {
14007 // does not exist and not asked to create it
14008 return status;
14009 } else {
14010 //printf("db_get_value_string: creating [%s]\n", key_name);
14011 status = db_create_key(hdb, hKeyRoot, key_name, TID_STRING);
14012 if (status != DB_SUCCESS)
14013 return status;
14014 status = db_find_key(hdb, hKeyRoot, key_name, &hkey);
14015 if (status != DB_SUCCESS)
14016 return status;
14017 assert(s != NULL);
14018 if (create_string_length == 0) {
14019 int size = s->length() + 1; // 1 byte for final \0
14020 status = db_set_data_index(hdb, hkey, s->c_str(), size, index, TID_STRING);
14021 } else {
14022 char* buf = (char*)malloc(create_string_length);
14023 assert(buf);
14024 mstrlcpy(buf, s->c_str(), create_string_length);
14025 status = db_set_data_index(hdb, hkey, buf, create_string_length, index, TID_STRING);
14026 free(buf);
14027 }
14028 if (status != DB_SUCCESS)
14029 return status;
14030 //printf("db_get_value_string: created with value [%s]\n", s->c_str());
14031 return DB_SUCCESS;
14032 }
14033 // NOT REACHED
14034}
INT db_set_data_index(HNDLE hDB, HNDLE hKey, const void *data, INT data_size, INT idx, DWORD type)
Definition odb.cxx:7668
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 3098 of file odb.cxx.

3099{
3100 if (hDB > _database_entries || hDB <= 0) {
3101 cm_msg(MERROR, "db_get_watchdog_info", "invalid database handle");
3102 return DB_INVALID_HANDLE;
3103 }
3104
3105 if (!_database[hDB - 1].attached) {
3106 cm_msg(MERROR, "db_get_watchdog_info", "invalid database handle");
3107 return DB_INVALID_HANDLE;
3108 }
3109
3110 /* lock database */
3112
3113 DATABASE *pdb = &_database[hDB - 1];
3114 DATABASE_HEADER *pheader = pdb->database_header;
3115
3116 /* find client */
3117 for (int i = 0; i < pheader->max_client_index; i++) {
3118 DATABASE_CLIENT *pclient = &pheader->client[i];
3119 if (pclient->pid && equal_ustring(pclient->name, client_name)) {
3120 *timeout = pclient->watchdog_timeout;
3121 *last = ss_millitime() - pclient->last_activity;
3123 return DB_SUCCESS;
3124 }
3125 }
3126
3127 *timeout = *last = 0;
3128
3130
3131 return CM_NO_CLIENT;
3132}
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 8139 of file odb.cxx.

8140{
8141 struct stat stat_buf;
8142 INT hfile, size, n, i, status;
8143 char *buffer;
8144
8145 if (rpc_is_remote() && bRemote)
8146 return rpc_call(RPC_DB_LOAD, hDB, hKeyRoot, filename);
8147
8148 /* open file */
8149 hfile = open(filename, O_RDONLY | O_TEXT, 0644);
8150 if (hfile == -1) {
8151 cm_msg(MERROR, "db_load", "file \"%s\" not found", filename);
8152 return DB_FILE_ERROR;
8153 }
8154
8155 /* allocate buffer with file size */
8156 fstat(hfile, &stat_buf);
8157 size = stat_buf.st_size;
8158 buffer = (char *) malloc(size + 1);
8159
8160 if (buffer == NULL) {
8161 cm_msg(MERROR, "db_load", "cannot allocate ODB load buffer");
8162 close(hfile);
8163 return DB_NO_MEMORY;
8164 }
8165
8166 n = 0;
8167
8168 do {
8169 i = read(hfile, buffer + n, size - n);
8170 if (i <= 0)
8171 break;
8172 n += i;
8173 } while (TRUE);
8174
8175 buffer[n] = 0;
8176
8177 if (strncmp(buffer, "<?xml version=\"1.0\"", 19) == 0) {
8178 status = db_paste_xml(hDB, hKeyRoot, buffer);
8179 if (status != DB_SUCCESS)
8180 printf("Error in file \"%s\"\n", filename);
8181 } else if( buffer[0] == '{'){
8182 if(strrchr(buffer, '}')){
8183 status = db_paste_json(hDB, hKeyRoot, buffer);
8184 } else {
8186 }
8187 } else
8188 status = db_paste(hDB, hKeyRoot, buffer);
8189
8190 close(hfile);
8191 free(buffer);
8192
8193 return status;
8194}
#define DB_FILE_ERROR
Definition midas.h:648
#define O_TEXT
Definition msystem.h:227
INT db_paste_xml(HNDLE hDB, HNDLE hKeyRoot, const char *buffer)
Definition odb.cxx:9016
INT EXPRT db_paste_json(HNDLE hDB, HNDLE hKeyRoot, const char *buffer)
#define RPC_DB_LOAD
Definition mrpc.h:76
DWORD n[4]
Definition mana.cxx:247
#define read(n, a, f)
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 15 of file json_paste.cxx.

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

◆ db_lock_database() [1/2]

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 2493 of file odb.cxx.

2494{
2495#ifdef LOCAL_ROUTINES
2496 int status = 0;
2497 DATABASE* pdb = db_lock_database(hDB, &status, "db_lock_database", false);
2498 if (!pdb)
2499 return status;
2500 return DB_SUCCESS;
2501#else
2502 return DB_SUCCESS;
2503#endif
2504}
Here is the call graph for this function:

◆ db_lock_database() [2/2]

DATABASE * db_lock_database ( HNDLE  hDB,
int *  pstatus,
const char *  caller,
bool  check_attached = true 
)
static

Definition at line 2508 of file odb.cxx.

2509{
2510 if (hDB > _database_entries || hDB <= 0) {
2511 cm_msg(MERROR, caller, "invalid database handle %d, aborting...", hDB);
2513 abort();
2514 if (pstatus)
2515 *pstatus = DB_INVALID_HANDLE;
2516 return NULL;
2517 }
2518
2519 DATABASE* pdb = &_database[hDB-1];
2520
2521 if (check_attached && !pdb->attached) {
2522 cm_msg(MERROR, caller, "invalid database handle %d, aborting...", hDB);
2524 abort();
2525 if (pstatus)
2526 *pstatus = DB_INVALID_HANDLE;
2527 return NULL;
2528 }
2529
2530 if (hDB != pdb->hDB) {
2531 cm_msg(MERROR, "db_lock_database", "database handle mismatch %d vs %d, aborting...", hDB, pdb->hDB);
2533 abort();
2534 if (pstatus)
2535 *pstatus = DB_INVALID_HANDLE;
2536 return NULL;
2537 }
2538
2539 /* obtain access mutex in multi-thread applications */
2540 int status = ss_mutex_wait_for(pdb->mutex, pdb->timeout);
2541 if (status != SS_SUCCESS) {
2542 cm_msg(MERROR, "db_lock_database", "cannot lock ODB mutex, timeout %d ms, status %d, aborting...", pdb->timeout, status);
2544 abort();
2545 }
2546
2547 /* protect this function against recursive call from signal handlers */
2548 if (pdb->inside_lock_unlock) {
2549 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");
2550 abort();
2551 }
2552
2553 pdb->inside_lock_unlock = 1;
2554
2555 //static int x = 0;
2556 //x++;
2557 //if (x > 5000) {
2558 // printf("inside db_lock_database(), press Ctrl-C now!\n");
2559 // sleep(5);
2560 //}
2561
2562 // test recursive locking
2563 // static int out=0;
2564 // out++;
2565 // printf("HERE %d!\n", out);
2566 // if (out>10) abort();
2567 // db_lock_database(hDB);
2568 // printf("OUT %d!\n", out);
2569
2570 if (pdb->lock_cnt == 0) {
2571 pdb->lock_cnt = 1;
2572 /* wait max. 5 minutes for semaphore (required if locking process is being debugged) */
2574 if (status == SS_TIMEOUT) {
2575 cm_msg(MERROR, "db_lock_database", "cannot lock ODB semaphore, timeout %d ms, aborting...", pdb->timeout);
2577 //exit(1); // exit() calls ataxit() handlers, including midas disconnect experiment which will crash because ODB locking is hosed. cannot continue, must abort(). K.O. 13-OCT-2024.
2578 abort();
2579 }
2580 if (status != SS_SUCCESS) {
2581 cm_msg(MERROR, "db_lock_database", "cannot lock ODB semaphore, timeout %d ms, ss_semaphore_wait_for() status %d, aborting...", pdb->timeout, status);
2583 abort();
2584 }
2585 } else {
2586 pdb->lock_cnt++; // we have already the lock (recursive call), so just increase counter
2587 }
2588
2589#ifdef CHECK_LOCK_COUNT
2590 {
2591 std::string str = msprintf(str, "db_lock_database, lock_cnt=%d", pdb->lock_cnt);
2592 ss_stack_history_entry(str.c_str());
2593 }
2594#endif
2595
2596 if (pdb->protect) {
2597 if (pdb->database_header == NULL) {
2598 int status;
2599 assert(!pdb->protect_read);
2600 assert(!pdb->protect_write);
2601 status = ss_shm_unprotect(pdb->shm_handle, &pdb->shm_adr, pdb->shm_size, TRUE, FALSE, "db_lock_database");
2602 if (status != SS_SUCCESS) {
2603 cm_msg(MERROR, "db_lock_database", "cannot lock ODB, ss_shm_unprotect(TRUE,FALSE) failed with status %d, aborting...", status);
2606 abort();
2607 }
2608 pdb->database_header = (DATABASE_HEADER *) pdb->shm_adr;
2609 pdb->protect_read = TRUE;
2610 pdb->protect_write = FALSE;
2611 }
2612 }
2613
2614 pdb->inside_lock_unlock = 0;
2615
2616 return pdb;
2617}
#define SS_TIMEOUT
Definition midas.h:675
void ss_stack_history_entry(char *tag)
Definition system.cxx:8100
INT ss_semaphore_wait_for(HNDLE semaphore_handle, DWORD timeout_millisec)
Definition system.cxx:2711
INT ss_mutex_wait_for(MUTEX_T *mutex, INT timeout)
Definition system.cxx:3109
INT timeout
Definition msystem.h:465
HNDLE hDB
Definition msystem.h:450
BOOL inside_lock_unlock
Definition msystem.h:466
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 7941 of file odb.cxx.

7966{
7967 HNDLE hKey;
7968 INT status, old_size;
7969
7970 if (num_values == 0)
7971 return DB_INVALID_PARAM;
7972
7973 status = db_find_key(hDB, hKeyRoot, name, &hKey);
7974 if (status != DB_SUCCESS) {
7975 db_create_key(hDB, hKeyRoot, name, type);
7976 status = db_find_key(hDB, hKeyRoot, name, &hKey);
7977 if (status != DB_SUCCESS)
7978 return status;
7979 status = db_set_data(hDB, hKey, data, data_size, num_values, type);
7980 } else {
7981 old_size = data_size;
7982 db_get_data(hDB, hKey, data, &old_size, type);
7983 status = db_set_data(hDB, hKey, data, data_size, num_values, type);
7984 }
7985
7986 return status;
7987}
INT db_set_data(HNDLE hDB, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type)
Definition odb.cxx:7239
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 142 of file odb.cxx.

143{
144 if (!msgp)
145 return;
146
147 va_list argptr;
148 char message[1000];
149
150 /* print argument list into message */
151 va_start(argptr, format);
152 vsnprintf(message, sizeof(message)-1, format, argptr);
153 va_end(argptr);
154 message[sizeof(message)-1] = 0; // ensure string is NUL-terminated
155
156 if (strlen(message) >= sizeof(message) - 2) {
157 const char* s = "!db_msg too long!";
158 memcpy(message + strlen(message) - strlen(s), s, strlen(s));
159 }
160
161 db_err_msg* msg = new db_err_msg;
162
163 msg->next = NULL;
164 msg->message_type = message_type;
165 msg->filename = filename;
166 msg->line = line;
167 msg->routine = routine;
168 msg->text = message;
169
171
172 //printf("new message:\n");
173 //db_print_msg(msg);
174
175 if (*msgp == NULL) {
176 *msgp = msg;
177 return;
178 }
179
180 // append new message to the end of the list
181 db_err_msg *m = (*msgp);
182 while (m->next != NULL) {
183 m = m->next;
184 }
185 assert(m->next == NULL);
186 m->next = msg;
187
188 //printf("Message list with added new message:\n");
189 //db_print_msg(*msgp);
190 return;
191}
static db_err_msg * _last_error_message
Definition odb.cxx:132
struct db_err_msg_struct db_err_msg
Definition odb.cxx:70
#define message(type, str)
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 12625 of file odb.cxx.

12632{
12633 if (rpc_is_remote()) {
12634 cm_msg(MERROR, "db_notify_clients", "db_notify_clients() does not work in remotely connected MIDAS clients");
12635 return DB_INVALID_HANDLE;
12636 }
12637
12638#ifdef LOCAL_ROUTINES
12639 {
12640 db_err_msg* msg = NULL;
12642 if (status != DB_SUCCESS)
12643 return status;
12644 DATABASE* pdb = &_database[hDB - 1];
12645 db_notify_clients_locked(pdb, hKeyMod, index, bWalk, &msg);
12647 if (msg)
12648 db_flush_msg(&msg);
12649 }
12650#endif
12651 return DB_SUCCESS;
12652}
static int db_notify_clients_locked(const DATABASE *pdb, HNDLE hKeyMod, int index, BOOL bWalk, db_err_msg **msg)
Definition odb.cxx:12569
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 12654 of file odb.cxx.

12666{
12667 if (rpc_is_remote())
12668 return rpc_call(RPC_DB_NOTIFY_CLIENTS_ARRAY, hDB, hKeys, size);
12669
12670#ifdef LOCAL_ROUTINES
12671 {
12673 if (status != DB_SUCCESS)
12674 return status;
12675 db_err_msg* msg = NULL;
12676 DATABASE* pdb = &_database[hDB - 1];
12677 int count = size/sizeof(INT);
12678 for (int i=0 ; i<count; i++) {
12679 db_notify_clients_locked(pdb, hKeys[i], -1, TRUE, &msg);
12680 }
12682 if (msg)
12683 db_flush_msg(&msg);
12684 }
12685#endif
12686 return DB_SUCCESS;
12687}
#define RPC_DB_NOTIFY_CLIENTS_ARRAY
Definition mrpc.h:97
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 pdb,
HNDLE  hKeyMod,
int  index,
BOOL  bWalk,
db_err_msg **  msg 
)
static

Definition at line 12569 of file odb.cxx.

12577{
12578 HNDLE hKey;
12579 KEYLIST *pkeylist;
12580 INT i, j;
12581 int status;
12582
12583 const DATABASE_HEADER* pheader = pdb->database_header;
12584
12585 hKey = hKeyMod;
12586
12587 const KEY* pkey = db_get_pkey(pheader, hKey, &status, "db_notify_clients", msg);
12588
12589 if (!pkey) {
12590 return status;
12591 }
12592
12593 do {
12594
12595 /* check which client has record open */
12596 if (pkey->notify_count)
12597 for (i = 0; i < pheader->max_client_index; i++) {
12598 const DATABASE_CLIENT* pclient = &pheader->client[i];
12599 for (j = 0; j < pclient->max_index; j++)
12600 if (pclient->open_record[j].handle == hKey) {
12601 /* send notification to remote process */
12602 std::string str = msprintf("O %d %d %d %d", pdb->hDB, hKey, hKeyMod, index);
12603 ss_resume(pclient->port, str.c_str());
12604 }
12605 }
12606
12607 if (pkey->parent_keylist == 0 || !bWalk)
12608 return DB_SUCCESS;
12609
12610 // FIXME: validate pkey->parent_keylist
12611 pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
12612 pkey = db_get_pkey(pheader, pkeylist->parent, &status, "db_notify_clients", msg);
12613 if (!pkey) {
12614 return status;
12615 }
12616 hKey = db_pkey_to_hkey(pheader, pkey);
12617 } while (TRUE);
12618
12619}
INT ss_resume(INT port, const char *message)
Definition system.cxx:4916
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 1820 of file odb.cxx.

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

13324{
13325 INT idx, status, size;
13326 KEY key;
13327 void *data;
13328
13329 /* allocate new space for the local record list */
13330 if (_record_list_entries == 0) {
13331 _record_list = (RECORD_LIST *) malloc(sizeof(RECORD_LIST));
13332 assert(_record_list != NULL);
13333 memset(_record_list, 0, sizeof(RECORD_LIST));
13334 if (_record_list == NULL) {
13335 cm_msg(MERROR, "db_open_record", "not enough memory");
13336 return DB_NO_MEMORY;
13337 }
13338
13340 idx = 0;
13341 } else {
13342 /* check for a deleted entry */
13343 for (idx = 0; idx < _record_list_entries; idx++)
13344 if (!_record_list[idx].handle)
13345 break;
13346
13347 /* if not found, create new one */
13348 if (idx == _record_list_entries) {
13350 if (_record_list == NULL) {
13351 cm_msg(MERROR, "db_open_record", "not enough memory");
13352 return DB_NO_MEMORY;
13353 }
13354
13355 memset(&_record_list[_record_list_entries], 0, sizeof(RECORD_LIST));
13356
13358 }
13359 }
13360
13361 db_get_key(hDB, hKey, &key);
13362
13363 /* check record size */
13364 status = db_get_record_size(hDB, hKey, 0, &size);
13365 if (status != DB_SUCCESS) {
13367 cm_msg(MERROR, "db_open_record", "cannot get record size, db_get_record_size() status %d", status);
13368 return DB_NO_MEMORY;
13369 }
13370
13371 if (size != rec_size && ptr != NULL) {
13373 std::string path = db_get_path(hDB, hKey);
13374 cm_msg(MERROR, "db_open_record", "struct size mismatch for \"%s\" (expected size: %d, size in ODB: %d)", path.c_str(), rec_size, size);
13376 }
13377
13378 /* check for read access */
13379 if (((key.access_mode & MODE_EXCLUSIVE) && (access_mode & MODE_WRITE))
13380 || (!(key.access_mode & MODE_WRITE) && (access_mode & MODE_WRITE))
13381 || (!(key.access_mode & MODE_READ) && (access_mode & MODE_READ))) {
13383 return DB_NO_ACCESS;
13384 }
13385
13386 if (access_mode & MODE_ALLOC) {
13387 data = malloc(size);
13388
13389 if (data == NULL) {
13391 cm_msg(MERROR, "db_open_record", "not enough memory, malloc(%d) returned NULL", size);
13392 return DB_NO_MEMORY;
13393 }
13394
13395 memset(data, 0, size);
13396
13397 *((void **) ptr) = data;
13398 } else {
13399 data = ptr;
13400 }
13401
13402 /* copy record to local memory */
13403 if (access_mode & MODE_READ && data != NULL) {
13404 status = db_get_record(hDB, hKey, data, &size, 0);
13405 if (status != DB_SUCCESS) {
13407 cm_msg(MERROR, "db_open_record", "cannot get record, db_get_record() status %d", status);
13408 return DB_NO_MEMORY;
13409 }
13410 }
13411
13412 /* copy local record to ODB */
13413 if (access_mode & MODE_WRITE) {
13414 /* only write to ODB if not in MODE_ALLOC */
13415 if ((access_mode & MODE_ALLOC) == 0) {
13416 status = db_set_record(hDB, hKey, data, size, 0);
13417 if (status != DB_SUCCESS) {
13419 cm_msg(MERROR, "db_open_record", "cannot set record, db_set_record() status %d", status);
13420 return DB_NO_MEMORY;
13421 }
13422 }
13423
13424 /* init a local copy of the record */
13425 _record_list[idx].copy = malloc(size);
13426 if (_record_list[idx].copy == NULL) {
13427 cm_msg(MERROR, "db_open_record", "not enough memory");
13428 return DB_NO_MEMORY;
13429 }
13430
13431 memcpy(_record_list[idx].copy, data, size);
13432 }
13433
13434 /* initialize record list */
13435 _record_list[idx].handle = hKey;
13436 _record_list[idx].hDB = hDB;
13437 _record_list[idx].access_mode = access_mode;
13438 _record_list[idx].data = data;
13439 _record_list[idx].buf_size = size;
13440 _record_list[idx].dispatcher = dispatcher;
13441 _record_list[idx].info = info;
13442
13443 /* add record entry in database structure */
13444 return db_add_open_record(hDB, hKey, (WORD) (access_mode & ~MODE_ALLOC));
13445}
INT db_set_record(HNDLE hDB, HNDLE hKey, void *data, INT buf_size, INT align)
Definition odb.cxx:12320
INT db_add_open_record(HNDLE hDB, HNDLE hKey, WORD access_mode)
Definition odb.cxx:12393
WORD access_mode
Definition msystem.h:475
void(* dispatcher)(INT, INT, void *)
Definition msystem.h:479
void * info
Definition msystem.h:480
INT buf_size
Definition msystem.h:478
HNDLE handle
Definition msystem.h:473
HNDLE hDB
Definition msystem.h:474
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 13473 of file odb.cxx.

13476{
13477 if (rec_str) {
13478 int status;
13479 if (rec_size) {
13480 char* pbuf;
13481 int size = rec_size;
13482 pbuf = (char*)malloc(size);
13483 assert(pbuf != NULL);
13484 status = db_get_record1(hDB, hKey, pbuf, &size, 0, rec_str);
13485 free(pbuf);
13486 if (status != DB_SUCCESS)
13487 return status;
13488 }
13489
13490 status = db_check_record(hDB, hKey, "", rec_str, TRUE);
13491 if (status != DB_SUCCESS)
13492 return status;
13493 }
13494
13495 return db_open_record(hDB, hKey, ptr, rec_size, access_mode, dispatcher, info);
13496}
INT db_get_record1(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT align, const char *rec_str)
Definition odb.cxx:11834
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 11895 of file odb.cxx.

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

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

688{
689 std::string path = db_get_path(hDB, hKeyRoot);
690
691 //printf("db_paste_json: handle %d, path [%s]\n", hKeyRoot, path.c_str());
692
693 MJsonNode* node = MJsonNode::Parse(buffer);
694 int status = paste_node(hDB, hKeyRoot, path.c_str(), false, 0, node, 0, 0, NULL);
695 delete node;
696
697 return status;
698}
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)
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 700 of file json_paste.cxx.

701{
702 int status;
703 KEY key;
704
705 status = db_get_key(hDB, hKeyRoot, &key);
706 if (status != DB_SUCCESS)
707 return status;
708
709 std::string path = db_get_path(hDB, hKeyRoot);
710
711 int tid = key.type;
712 int string_length = 0;
713 bool is_array = (key.num_values > 1);
714 if (tid == TID_STRING) {
715 // do not truncate strings, only extend if necessary
716 if ((int)node->GetString().length()+1 > key.item_size)
717 string_length = node->GetString().length()+1;
718 else
719 string_length = key.item_size;
720 }
721
722 status = paste_node(hDB, hKeyRoot, path.c_str(), is_array, index, node, tid, string_length, NULL);
723
724 return status;
725}
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 8798 of file odb.cxx.

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

9017{
9018 char error[256];
9019 INT status;
9020 PMXML_NODE tree, node;
9021
9022 if (hKeyRoot == 0)
9023 db_find_key(hDB, hKeyRoot, "", &hKeyRoot);
9024
9025 /* parse XML buffer */
9026 tree = mxml_parse_buffer(buffer, error, sizeof(error), NULL);
9027 if (tree == NULL) {
9028 puts(error);
9029 return DB_TYPE_MISMATCH;
9030 }
9031
9032 node = mxml_find_node(tree, "odb");
9033 if (node == NULL) {
9034 puts("Cannot find element \"odb\" in XML data");
9035 return DB_TYPE_MISMATCH;
9036 }
9037
9038 status = db_paste_node(hDB, hKeyRoot, node);
9039
9040 mxml_free_tree(tree);
9041
9042 return status;
9043}
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 1052 of file odb.cxx.

1053{
1054 return (POINTER_T) pkey - (POINTER_T) pheader;
1055}
Here is the caller graph for this function:

◆ db_print_hkey()

static void db_print_hkey ( const DATABASE_HEADER pheader,
HNDLE  hkey,
int  recurse = 0,
const char *  path = NULL,
HNDLE  parenthkeylist = 0 
)
static

Definition at line 1162 of file odb.cxx.

1163{
1164 const KEY *pkey = db_get_pkey(pheader, hkey, NULL, "db_print_key", NULL);
1165
1166 if (!pkey) {
1167 return;
1168 }
1169
1170 db_print_pkey(pheader, pkey, recurse, path, parenthkeylist);
1171}
static void db_print_pkey(const DATABASE_HEADER *pheader, const KEY *pkey, int recurse=0, const char *path=NULL, HNDLE parenthkeylist=0)
Definition odb.cxx:1138
Here is the call graph for this function:

◆ db_print_msg()

void db_print_msg ( const db_err_msg msg)
static

Definition at line 134 of file odb.cxx.

135{
136 while (msg != NULL) {
137 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());
138 msg = msg->next;
139 }
140}
Here is the caller graph for this function:

◆ db_print_pkey()

static void db_print_pkey ( const DATABASE_HEADER pheader,
const KEY pkey,
int  recurse = 0,
const char *  path = NULL,
HNDLE  parenthkeylist = 0 
)
static

Definition at line 1138 of file odb.cxx.

1139{
1140 HNDLE hkey = db_pkey_to_hkey(pheader, pkey);
1141
1142 std::string xpath;
1143 if (path == NULL) {
1144 xpath = db_get_path_pkey(pheader, pkey);
1145 path = xpath.c_str();
1146 }
1147
1148 printf("path \"%s\", parenthkey %d, hkey %d, name \"%s\", type %d, parent %d, data %d, total_size %d", path, parenthkeylist, hkey, pkey->name, pkey->type, pkey->parent_keylist, pkey->data, pkey->total_size);
1149
1150 if (pkey->type != TID_KEY) {
1151 printf("\n");
1152 } else {
1153 const KEYLIST *pkeylist = db_get_pkeylist(pheader, pkey, "db_validate_key", NULL);
1154
1155 if (pkeylist) {
1156 printf(", pkeylist parent %d, num_keys %d, first_key %d", pkeylist->parent, pkeylist->num_keys, pkeylist->first_key);
1157 printf("\n");
1158 }
1159 }
1160}
Here is the call graph for this function:
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 3251 of file odb.cxx.

3252{
3253 if (rpc_is_remote())
3254 return DB_SUCCESS;
3255
3256#ifdef LOCAL_ROUTINES
3257 if (hDB > _database_entries || hDB <= 0) {
3258 cm_msg(MERROR, "db_protect_database", "invalid database handle %d", hDB);
3259 return DB_INVALID_HANDLE;
3260 }
3261
3262 _database[hDB - 1].protect = TRUE;
3263 ss_shm_protect(_database[hDB - 1].shm_handle, _database[hDB - 1].database_header, _database[hDB - 1].shm_size);
3264 _database[hDB - 1].database_header = NULL;
3265#endif /* LOCAL_ROUTINES */
3266 return DB_SUCCESS;
3267}
INT ss_shm_protect(HNDLE handle, void *adr, size_t shm_size)
Definition system.cxx:1005
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 ( const DATABASE pdb,
const KEY pkey,
void **  data,
INT total_size,
INT  base_align,
INT max_align,
BOOL  bSet,
INT  convert_flags,
db_err_msg **  msg 
)
static

Definition at line 11461 of file odb.cxx.

11470{
11471 const KEY *pold;
11472 INT size, align, corr, total_size_tmp;
11473
11474 const DATABASE_HEADER* pheader = pdb->database_header;
11475
11476 const KEYLIST *pkeylist = (const KEYLIST *) ((const char *) pheader + pkey->data);
11477 if (!pkeylist->first_key)
11478 return;
11479
11480 // FIXME: validate pkeylist->first_key
11481 // FIXME: confusing reuse of pkey
11482 pkey = (const KEY *) ((char *) pheader + pkeylist->first_key);
11483
11484 /* first browse through this level */
11485 do {
11486 pold = NULL;
11487
11488 if (pkey->type == TID_LINK) {
11489 const KEY *plink = db_resolve_link_locked(pheader, pkey, NULL, msg);
11490
11491 if (!plink)
11492 return;
11493
11494 if (plink->type == TID_KEY) {
11495 db_recurse_record_tree_locked(pdb, plink, data, total_size, base_align, NULL, bSet, convert_flags, msg);
11496 } else {
11497 pold = pkey;
11498 pkey = plink;
11499 }
11500 }
11501
11502 if (pkey->type != TID_KEY) {
11503 /* correct for alignment */
11504 align = 1;
11505
11506 if (rpc_tid_size(pkey->type))
11507 align = rpc_tid_size(pkey->type) < base_align ? rpc_tid_size(pkey->type) : base_align;
11508
11509 if (max_align && align > *max_align)
11510 *max_align = align;
11511
11512 corr = VALIGN(*total_size, align) - *total_size;
11513 *total_size += corr;
11514 if (data)
11515 *data = (void *) ((char *) (*data) + corr);
11516
11517 /* calculate data size */
11518 size = pkey->item_size * pkey->num_values;
11519
11520 if (data) {
11521 if (bSet) {
11522 KEY* wpkey = (KEY*)pkey;
11523 /* copy data if there is write access */
11524 if (pkey->access_mode & MODE_WRITE) {
11525 memcpy((char *) pheader + pkey->data, *data, pkey->item_size * pkey->num_values);
11526
11527 /* convert data */
11528 if (convert_flags) {
11529 if (pkey->num_values > 1)
11530 rpc_convert_data((char *) pheader + pkey->data,
11531 pkey->type, RPC_FIXARRAY, pkey->item_size * pkey->num_values, convert_flags);
11532 else
11533 rpc_convert_single((char *) pheader + pkey->data, pkey->type, 0, convert_flags);
11534 }
11535
11536 /* update time */
11537 wpkey->last_written = ss_time();
11538
11539 /* notify clients which have key open */
11540 db_notify_clients_locked(pdb, db_pkey_to_hkey(pheader, pkey), -1, TRUE, msg);
11541 }
11542 } else {
11543 /* copy key data if there is read access */
11544 if (pkey->access_mode & MODE_READ) {
11545 memcpy(*data, (char *) pheader + pkey->data, pkey->item_size * pkey->num_values);
11546
11547 /* convert data */
11548 if (convert_flags) {
11549 if (pkey->num_values > 1)
11550 rpc_convert_data(*data, pkey->type,
11552 pkey->item_size * pkey->num_values, convert_flags);
11553 else
11554 rpc_convert_single(*data, pkey->type, RPC_OUTGOING, convert_flags);
11555 }
11556 }
11557 }
11558
11559 *data = (char *) (*data) + size;
11560 }
11561
11562 *total_size += size;
11563 } else {
11564 /* align new substructure according to the maximum
11565 align value in this structure */
11566 align = 1;
11567
11568 total_size_tmp = *total_size;
11569 db_recurse_record_tree_locked(pdb, pkey, NULL, &total_size_tmp, base_align, &align, bSet, convert_flags, msg);
11570
11571 if (max_align && align > *max_align)
11572 *max_align = align;
11573
11574 corr = VALIGN(*total_size, align) - *total_size;
11575 *total_size += corr;
11576 if (data)
11577 *data = (void *) ((char *) (*data) + corr);
11578
11579 /* now recurse subtree */
11580 db_recurse_record_tree_locked(pdb, pkey, data, total_size, base_align, NULL, bSet, convert_flags, msg);
11581
11582 corr = VALIGN(*total_size, align) - *total_size;
11583 *total_size += corr;
11584 if (data)
11585 *data = (void *) ((char *) (*data) + corr);
11586 }
11587
11588 if (pold) {
11589 pkey = pold;
11590 pold = NULL;
11591 }
11592
11593 if (!pkey->next_key)
11594 break;
11595
11596 // FIXME: validate pkey->next_key
11597 pkey = (KEY *) ((char *) pheader + pkey->next_key);
11598 } while (TRUE);
11599}
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 ( const DATABASE pdb,
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 11601 of file odb.cxx.

11610{
11611 /* get first subkey of hKey */
11612
11613 const KEY* pkey = db_get_pkey(pdb->database_header, hKey, NULL, "db_recurse_record_tree", msg);
11614
11615 if (!pkey) {
11616 return;
11617 }
11618
11619 db_recurse_record_tree_locked(pdb, pkey, data, total_size, base_align, max_align, bSet, convert_flags, msg);
11620}
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 12528 of file odb.cxx.

12536{
12537 if (rpc_is_remote())
12539
12540 int status = DB_SUCCESS;
12541
12542#ifdef LOCAL_ROUTINES
12543 {
12544 if (hDB > _database_entries || hDB <= 0) {
12545 cm_msg(MERROR, "db_remove_open_record", "invalid database handle %d", hDB);
12546 return DB_INVALID_HANDLE;
12547 }
12548
12550
12551 DATABASE *pdb = &_database[hDB - 1];
12552 DATABASE_HEADER *pheader = pdb->database_header;
12553
12554 db_allow_write_locked(pdb, "db_remove_open_record");
12555
12556 status = db_remove_open_record_wlocked(pdb, pheader, hKey);
12557
12559 }
12560#endif /* LOCAL_ROUTINES */
12561
12562 return status;
12563}
#define RPC_DB_REMOVE_OPEN_RECORD
Definition mrpc.h:74
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 12482 of file odb.cxx.

12483{
12484 int status = DB_SUCCESS;
12485
12487
12488 /* search key */
12489 int idx;
12490 for (idx = 0; idx < pclient->max_index; idx++)
12491 if (pclient->open_record[idx].handle == hKey)
12492 break;
12493
12494 if (idx == pclient->max_index) {
12495 return DB_INVALID_HANDLE;
12496 }
12497
12498 KEY* pkey = (KEY*)db_get_pkey(pheader, hKey, &status, "db_remove_open_record_wlocked", NULL);
12499
12500 if (!pkey)
12501 return status;
12502
12503 /* decrement notify_count */
12504
12505 if (pkey->notify_count > 0)
12506 pkey->notify_count--;
12507
12508 pclient->num_open_records--;
12509
12510 /* remove exclusive flag */
12511 if (pclient->open_record[idx].access_mode & MODE_WRITE)
12512 db_set_mode_wlocked(pheader, pkey, (WORD) (pkey->access_mode & ~MODE_EXCLUSIVE), 2, NULL);
12513
12514 memset(&pclient->open_record[idx], 0, sizeof(OPEN_RECORD));
12515
12516 /* calculate new max_index entry */
12517 int i;
12518 for (i = pclient->max_index - 1; i >= 0; i--)
12519 if (pclient->open_record[i].handle != 0)
12520 break;
12521 pclient->max_index = i + 1;
12522
12523 return DB_SUCCESS;
12524}
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 6285 of file odb.cxx.

6306{
6307 if (rpc_is_remote())
6309
6310#ifdef LOCAL_ROUTINES
6311 {
6312 DATABASE_HEADER *pheader;
6313 KEY *pkey;
6314 int status;
6315
6316 if (hDB > _database_entries || hDB <= 0) {
6317 cm_msg(MERROR, "db_rename_key", "invalid database handle");
6318 return DB_INVALID_HANDLE;
6319 }
6320
6321 if (!_database[hDB - 1].attached) {
6322 cm_msg(MERROR, "db_rename_key", "invalid database handle");
6323 return DB_INVALID_HANDLE;
6324 }
6325
6326 if (hKey < (int) sizeof(DATABASE_HEADER)) {
6327 cm_msg(MERROR, "db_rename_key", "invalid key handle");
6328 return DB_INVALID_HANDLE;
6329 }
6330
6331 db_err_msg* msg = NULL;
6332 status = db_validate_name(name, FALSE, "db_rename_key", &msg);
6333 if (msg)
6334 db_flush_msg(&msg);
6335 if (status != DB_SUCCESS)
6336 return status;
6337
6338 if (name == NULL) {
6339 cm_msg(MERROR, "db_rename_key", "key name is NULL");
6340 return DB_INVALID_NAME;
6341 }
6342
6343 if (strlen(name) < 1) {
6344 cm_msg(MERROR, "db_rename_key", "key name is too short");
6345 return DB_INVALID_NAME;
6346 }
6347
6348 if (strchr(name, '/')) {
6349 cm_msg(MERROR, "db_rename_key", "key name may not contain \"/\"");
6350 return DB_INVALID_NAME;
6351 }
6352
6354
6355 pheader = _database[hDB - 1].database_header;
6356
6357 /* check if hKey argument is correct */
6358 if (!db_validate_hkey(pheader, hKey)) {
6360 return DB_INVALID_HANDLE;
6361 }
6362
6363 pkey = (KEY *) ((char *) pheader + hKey);
6364
6365 if (!pkey->type) {
6366 int pkey_type = pkey->type;
6368 cm_msg(MERROR, "db_rename_key", "hkey %d invalid key type %d", hKey, pkey_type);
6369 return DB_INVALID_HANDLE;
6370 }
6371
6372 db_allow_write_locked(&_database[hDB - 1], "db_rename_key");
6373
6374 mstrlcpy(pkey->name, name, NAME_LENGTH);
6375
6377
6378 }
6379#endif /* LOCAL_ROUTINES */
6380
6381 return DB_SUCCESS;
6382}
#define RPC_DB_RENAME_KEY
Definition mrpc.h:78
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 6385 of file odb.cxx.

6408{
6409 if (rpc_is_remote())
6410 return rpc_call(RPC_DB_REORDER_KEY, hDB, hKey, idx);
6411
6412#ifdef LOCAL_ROUTINES
6413 {
6414 DATABASE_HEADER *pheader;
6415 KEY *pkey, *pnext_key, *pkey_tmp;
6416 KEYLIST *pkeylist;
6417 INT i;
6418
6419 if (hDB > _database_entries || hDB <= 0) {
6420 cm_msg(MERROR, "db_rename_key", "invalid database handle");
6421 return DB_INVALID_HANDLE;
6422 }
6423
6424 if (!_database[hDB - 1].attached) {
6425 cm_msg(MERROR, "db_rename_key", "invalid database handle");
6426 return DB_INVALID_HANDLE;
6427 }
6428
6429 if (hKey < (int) sizeof(DATABASE_HEADER)) {
6430 cm_msg(MERROR, "db_rename_key", "invalid key handle");
6431 return DB_INVALID_HANDLE;
6432 }
6433
6435
6436 pheader = _database[hDB - 1].database_header;
6437
6438 /* check if hKey argument is correct */
6439 if (!db_validate_hkey(pheader, hKey)) {
6441 return DB_INVALID_HANDLE;
6442 }
6443
6444 pkey = (KEY *) ((char *) pheader + hKey);
6445
6446 if (!pkey->type) {
6447 int pkey_type = pkey->type;
6449 cm_msg(MERROR, "db_reorder_key", "hkey %d invalid key type %d", hKey, pkey_type);
6450 return DB_INVALID_HANDLE;
6451 }
6452
6453 if (!(pkey->access_mode & MODE_WRITE)) {
6455 return DB_NO_ACCESS;
6456 }
6457
6458 /* check if someone has opened key or parent */
6459 do {
6460#ifdef CHECK_OPEN_RECORD
6461 if (pkey->notify_count) {
6463 return DB_OPEN_RECORD;
6464 }
6465#endif
6466 if (pkey->parent_keylist == 0)
6467 break;
6468
6469 pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
6470 // FIXME: validate pkeylist->parent
6471 pkey = (KEY *) ((char *) pheader + pkeylist->parent);
6472 } while (TRUE);
6473
6474 db_allow_write_locked(&_database[hDB - 1], "db_reorder_key");
6475
6476 pkey = (KEY *) ((char *) pheader + hKey); // NB: hKey is already validated
6477 pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
6478
6479 /* first remove key from list */
6480 pnext_key = (KEY *) (POINTER_T) pkey->next_key; // FIXME: what is this pointer cast?
6481
6482 if ((KEY *) ((char *) pheader + pkeylist->first_key) == pkey) {
6483 /* key is first in list */
6484 pkeylist->first_key = (POINTER_T) pnext_key;
6485 } else {
6486 /* find predecessor */
6487 // FIXME: validate pkeylist->first_key
6488 pkey_tmp = (KEY *) ((char *) pheader + pkeylist->first_key);
6489 while ((KEY *) ((char *) pheader + pkey_tmp->next_key) != pkey) {
6490 // FIXME: validate pkey_tmp->next_key
6491 pkey_tmp = (KEY *) ((char *) pheader + pkey_tmp->next_key);
6492 }
6493 pkey_tmp->next_key = (POINTER_T) pnext_key;
6494 }
6495
6496 /* add key to list at proper index */
6497 // FIXME: validate pkeylist->first_key
6498 pkey_tmp = (KEY *) ((char *) pheader + pkeylist->first_key);
6499 if (idx < 0 || idx >= pkeylist->num_keys - 1) {
6500 /* add at bottom */
6501
6502 /* find last key */
6503 for (i = 0; i < pkeylist->num_keys - 2; i++) {
6504 // FIXME: validate pkey_tmp->next_key
6505 pkey_tmp = (KEY *) ((char *) pheader + pkey_tmp->next_key);
6506 }
6507
6508 pkey_tmp->next_key = (POINTER_T) pkey - (POINTER_T) pheader;
6509 pkey->next_key = 0;
6510 } else {
6511 if (idx == 0) {
6512 /* add at top */
6513 pkey->next_key = pkeylist->first_key;
6514 pkeylist->first_key = (POINTER_T) pkey - (POINTER_T) pheader;
6515 } else {
6516 /* add at position index */
6517 for (i = 0; i < idx - 1; i++) {
6518 // FIXME: validate pkey_tmp->next_key
6519 pkey_tmp = (KEY *) ((char *) pheader + pkey_tmp->next_key);
6520 }
6521
6522 pkey->next_key = pkey_tmp->next_key;
6523 pkey_tmp->next_key = (POINTER_T) pkey - (POINTER_T) pheader;
6524 }
6525 }
6526
6528
6529 }
6530#endif /* LOCAL_ROUTINES */
6531
6532 return DB_SUCCESS;
6533}
#define RPC_DB_REORDER_KEY
Definition mrpc.h:80
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 14058 of file odb.cxx.

14059{
14060 int status;
14061 int hkey;
14062
14063 //printf("db_resize_string: key_name [%s], num_values %d, max_string_length %d\n", key_name, num_values, max_string_length);
14064
14065 int old_num_values = 0;
14066 int old_item_size = 0;
14067 int old_size = 0;
14068 char* old_data = NULL;
14069
14070 if (key_name) {
14071 status = db_find_key(hdb, hKeyRoot, key_name, &hkey);
14072 } else {
14073 hkey = hKeyRoot;
14075 }
14076 if (status == DB_SUCCESS) {
14077 KEY key;
14078 status = db_get_key(hdb, hkey, &key);
14079 if (status != DB_SUCCESS)
14080 return status;
14081 old_num_values = key.num_values;
14082 old_item_size = key.item_size;
14083 old_size = old_num_values * old_item_size;
14084 if (old_size > 0) {
14085 old_data = (char*)malloc(old_size);
14086 assert(old_data != NULL);
14087 int size = old_size;
14088 status = db_get_data(hdb, hkey, old_data, &size, TID_STRING);
14089 if (status != DB_SUCCESS) {
14090 free(old_data);
14091 return status;
14092 }
14093 assert(size == old_size);
14094 }
14095 } else {
14096 status = db_create_key(hdb, hKeyRoot, key_name, TID_STRING);
14097 if (status != DB_SUCCESS)
14098 return status;
14099 status = db_find_key(hdb, hKeyRoot, key_name, &hkey);
14100 if (status != DB_SUCCESS)
14101 return status;
14102 }
14103
14104 //printf("old_num_values %d, old_item_size %d, old_size %d\n", old_num_values, old_item_size, old_size);
14105
14106 int item_size = max_string_length;
14107
14108 if (item_size < 1)
14109 item_size = old_item_size;
14110
14111 if (num_values < 1)
14112 num_values = old_num_values;
14113
14114 int new_size = num_values * item_size;
14115 char* new_data = (char*)malloc(new_size);
14116 assert(new_data);
14117
14118 memset(new_data, 0, new_size);
14119
14120 if (old_data) {
14121 int num = old_num_values;
14122 if (num > num_values)
14123 num = num_values;
14124
14125 //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);
14126
14127 for (int i=0; i<num; i++) {
14128 const char* old_ptr = old_data + i*old_item_size;
14129 char* new_ptr = new_data + i*item_size;
14130 mstrlcpy(new_ptr, old_ptr, item_size);
14131 }
14132 }
14133
14134 status = db_set_data(hdb, hkey, new_data, new_size, num_values, TID_STRING);
14135
14136 if (old_data)
14137 free(old_data);
14138 if (new_data)
14139 free(new_data);
14140
14141 return status;
14142}
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 1119 of file odb.cxx.

1120{
1121 if (pkey->type != TID_LINK)
1122 return pkey;
1123
1124 if (!db_validate_data_offset(pheader, pkey->data)) {
1125 db_msg(msg, MERROR, "db_resolve_link_locked", "invalid data offset %d for symlink \"%s\"", pkey->data, db_get_path_pkey(pheader, pkey).c_str());
1126 if (pstatus)
1127 *pstatus = DB_CORRUPTED;
1128 return NULL;
1129 }
1130
1131 if (*((char *) pheader + pkey->data) == '/') {
1132 return db_find_pkey_locked(pheader, NULL, (char*)pheader + pkey->data, true, pstatus, msg);
1133 } else {
1134 return db_find_pkey_locked(pheader, pkey, (char*)pheader + pkey->data, true, pstatus, msg);
1135 }
1136}
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 9263 of file odb.cxx.

9264{
9265 if (rpc_is_remote() && bRemote)
9266 return rpc_call(RPC_DB_SAVE, hDB, hKey, filename, bRemote);
9267
9268#ifdef LOCAL_ROUTINES
9269 {
9270 INT hfile, size, buffer_size, n, status;
9271 char *buffer;
9272
9273 /* open file */
9274 hfile = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, 0644);
9275 if (hfile == -1) {
9276 cm_msg(MERROR, "db_save", "Cannot open file \"%s\"", filename);
9277 return DB_FILE_ERROR;
9278 }
9279
9280 std::string path = db_get_path(hDB, hKey);
9281
9282 buffer_size = 10000;
9283 do {
9284 buffer = (char *) malloc(buffer_size);
9285 if (buffer == NULL) {
9286 cm_msg(MERROR, "db_save", "cannot allocate ODB dump buffer");
9287 break;
9288 }
9289
9290 size = buffer_size;
9291 status = db_copy(hDB, hKey, buffer, &size, path.c_str());
9292 if (status != DB_TRUNCATED) {
9293 n = write(hfile, buffer, buffer_size - size);
9294 free(buffer);
9295 buffer = NULL;
9296
9297 if (n != buffer_size - size) {
9298 cm_msg(MERROR, "db_save", "cannot save .ODB file");
9299 close(hfile);
9300 return DB_FILE_ERROR;
9301 }
9302 break;
9303 }
9304
9305 /* increase buffer size if truncated */
9306 free(buffer);
9307 buffer = NULL;
9308 buffer_size *= 2;
9309 } while (1);
9310
9311 close(hfile);
9312
9313 }
9314#endif /* LOCAL_ROUTINES */
9315
9316 return DB_SUCCESS;
9317}
#define RPC_DB_SAVE
Definition mrpc.h:75
#define write(n, a, f, d)
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 10548 of file odb.cxx.

10549{
10550 INT status;
10551
10552 /* open file */
10553 FILE *fp = fopen(filename, "w");
10554 if (fp == NULL) {
10555 cm_msg(MERROR, "db_save_json", "Cannot open file \"%s\", fopen() errno %d (%s)", filename, errno, strerror(errno));
10556 return DB_FILE_ERROR;
10557 }
10558
10559 bool unlock = false;
10560
10561 if (!rpc_is_remote()) {
10563 if (status != DB_SUCCESS) {
10564 fclose(fp);
10565 return status;
10566 }
10567 unlock = true;
10568 }
10569
10570 std::string path = db_get_path(hDB, hKey);
10571
10572 bool emptySubdir = false;
10573 HNDLE hSubKey;
10574 status = db_enum_link(hDB, hKey, 0, &hSubKey);
10576 emptySubdir = true;
10577
10578 char* buffer = NULL;
10579 int buffer_size = 0;
10580 int buffer_end = 0;
10581
10582 json_write(&buffer, &buffer_size, &buffer_end, 0, "{\n", 0);
10583
10584 json_write(&buffer, &buffer_size, &buffer_end, 1, "/MIDAS version", 1);
10585 json_write(&buffer, &buffer_size, &buffer_end, 0, " : ", 0);
10586 json_write(&buffer, &buffer_size, &buffer_end, 0, MIDAS_VERSION, 1);
10587 json_write(&buffer, &buffer_size, &buffer_end, 0, ",\n", 0);
10588
10589 json_write(&buffer, &buffer_size, &buffer_end, 1, "/MIDAS git revision", 1);
10590 json_write(&buffer, &buffer_size, &buffer_end, 0, " : ", 0);
10591 json_write(&buffer, &buffer_size, &buffer_end, 0, GIT_REVISION, 1);
10592 json_write(&buffer, &buffer_size, &buffer_end, 0, ",\n", 0);
10593
10594 json_write(&buffer, &buffer_size, &buffer_end, 1, "/filename", 1);
10595 json_write(&buffer, &buffer_size, &buffer_end, 0, " : ", 0);
10596 json_write(&buffer, &buffer_size, &buffer_end, 0, filename, 1);
10597 json_write(&buffer, &buffer_size, &buffer_end, 0, ",\n", 0);
10598
10599 json_write(&buffer, &buffer_size, &buffer_end, 1, "/ODB path", 1);
10600 json_write(&buffer, &buffer_size, &buffer_end, 0, " : ", 0);
10601 json_write(&buffer, &buffer_size, &buffer_end, 0, path.c_str(), 1);
10602
10603 if (emptySubdir)
10604 json_write(&buffer, &buffer_size, &buffer_end, 0, "", 0);
10605 else
10606 json_write(&buffer, &buffer_size, &buffer_end, 0, ",\n", 0);
10607
10608 //status = db_save_json_key_obsolete(hDB, hKey, -1, &buffer, &buffer_size, &buffer_end, 1, 0, 1);
10609 status = json_write_bare_subdir(hDB, hKey, &buffer, &buffer_size, &buffer_end, JS_LEVEL_1, flags, 0);
10610
10611 json_write(&buffer, &buffer_size, &buffer_end, 0, "\n}\n", 0);
10612
10613 if (unlock) {
10615 }
10616
10617 if (status == DB_SUCCESS) {
10618 if (buffer) {
10619 size_t wr = fwrite(buffer, 1, buffer_end, fp);
10620 if (wr != (size_t)buffer_end) {
10621 cm_msg(MERROR, "db_save_json", "Cannot write to file \"%s\", fwrite() errno %d (%s)", filename, errno, strerror(errno));
10622 free(buffer);
10623 fclose(fp);
10624 return DB_FILE_ERROR;
10625 }
10626 }
10627 }
10628
10629 if (buffer)
10630 free(buffer);
10631
10632 fclose(fp);
10633
10634 return DB_SUCCESS;
10635}
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:10375
#define MIDAS_VERSION
Definition midas.h:37
#define JS_LEVEL_1
Definition midas.h:1724
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 9834 of file odb.cxx.

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

10732{
10733 KEY key;
10734 char str[256], line[50+256];
10735 INT status, i, size, fh, buffer_size;
10736 char *buffer = NULL, *pc;
10737 int wr;
10738
10739
10740 /* open file */
10741 fh = open(file_name, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0644);
10742
10743 if (fh == -1) {
10744 cm_msg(MERROR, "db_save_string", "Cannot open file\"%s\"", file_name);
10745 return DB_FILE_ERROR;
10746 }
10747
10749 if (status != DB_SUCCESS) {
10750 cm_msg(MERROR, "db_save_string", "cannot find key");
10751 return DB_INVALID_HANDLE;
10752 }
10753
10754 if (string_name && string_name[0])
10755 strcpy(str, string_name);
10756 else
10757 strcpy(str, key.name);
10758
10759 name2c(str);
10760 for (i = 0; i < (int) strlen(str); i++)
10761 str[i] = (char) toupper(str[i]);
10762
10763 sprintf(line, "#define %s(_name) const char *_name[] = {\\\n", str);
10764 size = strlen(line);
10765 wr = write(fh, line, size);
10766 if (wr != size) {
10767 cm_msg(MERROR, "db_save", "file \"%s\" write error: write(%d) returned %d, errno %d (%s)", file_name, size, wr, errno, strerror(errno));
10768 close(fh);
10769 if (buffer)
10770 free(buffer);
10771 return DB_FILE_ERROR;
10772 }
10773
10774 buffer_size = 10000;
10775 do {
10776 buffer = (char *) malloc(buffer_size);
10777 if (buffer == NULL) {
10778 cm_msg(MERROR, "db_save", "cannot allocate ODB dump buffer");
10779 break;
10780 }
10781
10782 size = buffer_size;
10783 status = db_copy(hDB, hKey, buffer, &size, "");
10784 if (status != DB_TRUNCATED)
10785 break;
10786
10787 /* increase buffer size if truncated */
10788 free(buffer);
10789 buffer = NULL;
10790 buffer_size *= 2;
10791 } while (1);
10792
10793
10794 pc = buffer;
10795
10796 do {
10797 i = 0;
10798 line[i++] = '"';
10799 while (*pc != '\n' && *pc != 0) {
10800 if (*pc == '\"' || *pc == '\'')
10801 line[i++] = '\\';
10802 line[i++] = *pc++;
10803 }
10804 strcpy(&line[i], "\",\\\n");
10805 if (i > 0) {
10806 size = strlen(line);
10807 wr = write(fh, line, size);
10808 if (wr != size) {
10809 cm_msg(MERROR, "db_save", "file \"%s\" write error: write(%d) returned %d, errno %d (%s)", file_name, size, wr, errno, strerror(errno));
10810 close(fh);
10811 if (buffer)
10812 free(buffer);
10813 return DB_FILE_ERROR;
10814 }
10815 }
10816
10817 if (*pc == '\n')
10818 pc++;
10819
10820 } while (*pc);
10821
10822 sprintf(line, "NULL }\n\n");
10823 size = strlen(line);
10824 wr = write(fh, line, size);
10825 if (wr != size) {
10826 cm_msg(MERROR, "db_save", "file \"%s\" write error: write(%d) returned %d, errno %d (%s)", file_name, size, wr, errno, strerror(errno));
10827 close(fh);
10828 if (buffer)
10829 free(buffer);
10830 return DB_FILE_ERROR;
10831 }
10832
10833 close(fh);
10834 free(buffer);
10835
10836 return DB_SUCCESS;
10837}
void name2c(char *str)
Definition odb.cxx:9115
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 10648 of file odb.cxx.

10649{
10650 KEY key;
10651 char str[100], line[10+100];
10652 INT status, i, fh;
10653 int wr, size;
10654
10655 /* open file */
10656 fh = open(file_name, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0644);
10657
10658 if (fh == -1) {
10659 cm_msg(MERROR, "db_save_struct", "Cannot open file\"%s\"", file_name);
10660 return DB_FILE_ERROR;
10661 }
10662
10664 if (status != DB_SUCCESS) {
10665 cm_msg(MERROR, "db_save_struct", "cannot find key");
10666 return DB_INVALID_HANDLE;
10667 }
10668
10669 sprintf(line, "typedef struct {\n");
10670
10671 size = strlen(line);
10672 wr = write(fh, line, size);
10673 if (wr != size) {
10674 cm_msg(MERROR, "db_save_struct", "file \"%s\" write error: write(%d) returned %d, errno %d (%s)", file_name, size, wr, errno, strerror(errno));
10675 close(fh);
10676 return DB_FILE_ERROR;
10677 }
10678
10679 db_save_tree_struct(hDB, hKey, fh, 0);
10680
10681 if (struct_name && struct_name[0])
10682 mstrlcpy(str, struct_name, sizeof(str));
10683 else
10684 mstrlcpy(str, key.name, sizeof(str));
10685
10686 name2c(str);
10687 for (i = 0; i < (int) strlen(str); i++)
10688 str[i] = (char) toupper(str[i]);
10689
10690 sprintf(line, "} %s;\n\n", str);
10691
10692 size = strlen(line);
10693 wr = write(fh, line, size);
10694 if (wr != size) {
10695 cm_msg(MERROR, "db_save_struct", "file \"%s\" write error: write(%d) returned %d, errno %d (%s)", file_name, size, wr, errno, strerror(errno));
10696 close(fh);
10697 return DB_FILE_ERROR;
10698 }
10699
10700 close(fh);
10701
10702 return DB_SUCCESS;
10703}
static void db_save_tree_struct(HNDLE hDB, HNDLE hKey, int hfile, INT level)
Definition odb.cxx:9136
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 9136 of file odb.cxx.

9145{
9146 INT i, idx;
9147 KEY key;
9148 HNDLE hSubkey;
9149 int wr;
9150
9151 /* first enumerate this level */
9152 for (idx = 0;; idx++) {
9153 char name[MAX_ODB_PATH];
9154
9155 db_enum_link(hDB, hKey, idx, &hSubkey);
9156 if (!hSubkey)
9157 break;
9158
9159 /* first get the name of the link, than the type of the link target */
9161 mstrlcpy(name, key.name, sizeof(name));
9162 db_enum_key(hDB, hKey, idx, &hSubkey);
9163
9165
9166 if (key.type != TID_KEY) {
9167 char line[MAX_ODB_PATH];
9168 char str[MAX_ODB_PATH];
9169
9170 for (i = 0; i <= level; i++) {
9171 wr = write(hfile, " ", 2);
9172 assert(wr == 2);
9173 }
9174
9175 switch (key.type) {
9176 case TID_INT8:
9177 case TID_CHAR:
9178 strcpy(line, "char");
9179 break;
9180 case TID_INT16:
9181 strcpy(line, "short");
9182 break;
9183 case TID_FLOAT:
9184 strcpy(line, "float");
9185 break;
9186 case TID_DOUBLE:
9187 strcpy(line, "double");
9188 break;
9189 case TID_BITFIELD:
9190 strcpy(line, "unsigned char");
9191 break;
9192 case TID_STRING:
9193 strcpy(line, "char");
9194 break;
9195 case TID_LINK:
9196 strcpy(line, "char");
9197 break;
9198 default:
9199 strcpy(line, rpc_tid_name(key.type));
9200 break;
9201 }
9202
9203 mstrlcat(line, " ", sizeof(line));
9204 mstrlcpy(str, name, sizeof(str));
9205 name2c(str);
9206
9207 if (key.num_values > 1)
9208 sprintf(str + strlen(str), "[%d]", key.num_values);
9209 if (key.type == TID_STRING || key.type == TID_LINK)
9210 sprintf(str + strlen(str), "[%d]", key.item_size);
9211
9212 mstrlcpy(line + 10, str, sizeof(line) - 10);
9213 mstrlcat(line, ";\n", sizeof(line));
9214
9215 wr = write(hfile, line, strlen(line));
9216 assert(wr > 0);
9217 } else {
9218 char line[10+MAX_ODB_PATH];
9219 char str[MAX_ODB_PATH];
9220
9221 /* recurse subtree */
9222 for (i = 0; i <= level; i++) {
9223 wr = write(hfile, " ", 2);
9224 assert(wr == 2);
9225 }
9226
9227 sprintf(line, "struct {\n");
9228 wr = write(hfile, line, strlen(line));
9229 assert(wr > 0);
9230 db_save_tree_struct(hDB, hSubkey, hfile, level + 1);
9231
9232 for (i = 0; i <= level; i++) {
9233 wr = write(hfile, " ", 2);
9234 assert(wr == 2);
9235 }
9236
9237 strcpy(str, name);
9238 name2c(str);
9239
9240 sprintf(line, "} %s;\n", str);
9241 wr = write(hfile, line, strlen(line));
9242 assert(wr > 0);
9243 }
9244 }
9245}
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 9503 of file odb.cxx.

9504{
9505#ifdef LOCAL_ROUTINES
9506 {
9507 INT status;
9508 MXML_WRITER *writer;
9509
9510 /* open file */
9511 writer = mxml_open_file(filename);
9512 if (writer == NULL) {
9513 cm_msg(MERROR, "db_save_xml", "Cannot open file \"%s\"", filename);
9514 return DB_FILE_ERROR;
9515 }
9516
9517 std::string path = db_get_path(hDB, hKey);
9518
9519 /* write XML header */
9520 mxml_start_element(writer, "odb");
9521 mxml_write_attribute(writer, "root", path.c_str());
9522 mxml_write_attribute(writer, "filename", filename);
9523 mxml_write_attribute(writer, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
9524
9525 std::string xsd_path;
9526
9527 if (getenv("MIDASSYS"))
9528 xsd_path = getenv("MIDASSYS");
9529 else
9530 xsd_path = ".";
9531
9532 xsd_path += DIR_SEPARATOR_STR;
9533 xsd_path += "odb.xsd";
9534 mxml_write_attribute(writer, "xsi:noNamespaceSchemaLocation", xsd_path.c_str());
9535
9536 status = db_save_xml_key(hDB, hKey, 0, writer);
9537
9538 mxml_end_element(writer); // "odb"
9539 mxml_close_file(writer);
9540
9541 return status;
9542 }
9543#endif /* LOCAL_ROUTINES */
9544
9545 return DB_SUCCESS;
9546}
#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 9364 of file odb.cxx.

9365{
9366 INT i, idx, size, status;
9367 char *data;
9368 HNDLE hSubkey;
9369 KEY key;
9370
9371 if (level > MAX_ODB_PATH) {
9372 cm_msg(MERROR, "db_save_xml_key", "ODB path too long at \"%s\"", db_get_path(hDB, hKey).c_str());
9373 return DB_NO_MEMORY;
9374 }
9375
9377 if (status != DB_SUCCESS)
9378 return status;
9379
9380 if (key.type == TID_KEY) {
9381
9382 /* save opening tag for subtree */
9383
9384 if (level > 0) {
9385 mxml_start_element(writer, "dir");
9386 mxml_write_attribute(writer, "name", key.name);
9387 mxml_write_attribute(writer, "handle", std::to_string(hKey).c_str());
9388 }
9389
9390 for (idx = 0;; idx++) {
9391 db_enum_link(hDB, hKey, idx, &hSubkey);
9392
9393 if (!hSubkey)
9394 break;
9395
9396 /* save subtree */
9397 status = db_save_xml_key(hDB, hSubkey, level + 1, writer);
9398 if (status != DB_SUCCESS)
9399 return status;
9400 }
9401
9402 /* save closing tag for subtree */
9403 if (level > 0)
9404 mxml_end_element(writer);
9405
9406 } else {
9407 /* save key value */
9408
9409 if (key.num_values > 1)
9410 mxml_start_element(writer, "keyarray");
9411 else
9412 mxml_start_element(writer, "key");
9413 mxml_write_attribute(writer, "name", key.name);
9414 mxml_write_attribute(writer, "type", rpc_tid_name(key.type));
9415 mxml_write_attribute(writer, "handle", std::to_string(hKey).c_str());
9416
9417 if (key.type == TID_STRING || key.type == TID_LINK) {
9418 char str[256];
9419 sprintf(str, "%d", key.item_size);
9420 mxml_write_attribute(writer, "size", str);
9421 }
9422
9423 if (key.num_values > 1) {
9424 char str[256];
9425 sprintf(str, "%d", key.num_values);
9426 mxml_write_attribute(writer, "num_values", str);
9427 }
9428
9429 size = key.total_size;
9430 data = (char *) malloc(size+1); // an extra byte to zero-terminate strings
9431 if (data == NULL) {
9432 cm_msg(MERROR, "db_save_xml_key", "cannot allocate data buffer");
9433 return DB_NO_MEMORY;
9434 }
9435
9436 db_get_link_data(hDB, hKey, data, &size, key.type);
9437
9438 if (key.num_values == 1) {
9439 if (key.type == TID_STRING) {
9440 data[size] = 0; // make sure strings are NUL-terminated
9441 mxml_write_value(writer, data);
9442 } else {
9443 std::string str = db_sprintf(data, key.item_size, 0, key.type);
9444 if (key.type == TID_STRING && strlen(data) >= MAX_STRING_LENGTH) {
9445 std::string path = db_get_path(hDB, hKey);
9446 cm_msg(MERROR, "db_save_xml_key", "Long odb string probably truncated, odb path \"%s\", string length %d truncated to %d", path.c_str(), (int)strlen(data), (int)str.length());
9447 }
9448 mxml_write_value(writer, str.c_str());
9449 }
9450 mxml_end_element(writer);
9451
9452 } else { /* array of values */
9453
9454 for (i = 0; i < key.num_values; i++) {
9455
9456 mxml_start_element(writer, "value");
9457
9458 {
9459 char str[256];
9460 sprintf(str, "%d", i);
9461 mxml_write_attribute(writer, "index", str);
9462 }
9463
9464 if (key.type == TID_STRING) {
9465 char* p = data + i * key.item_size;
9466 p[key.item_size - 1] = 0; // make sure string is NUL-terminated
9467 //cm_msg(MINFO, "db_save_xml_key", "odb string array item_size %d, index %d length %d", key.item_size, i, (int)strlen(p));
9468 mxml_write_value(writer, p);
9469 } else {
9470 std::string str = db_sprintf(data, key.item_size, i, key.type);
9471 if ((key.type == TID_STRING) && (str.length() >= MAX_STRING_LENGTH-1)) {
9472 std::string path = db_get_path(hDB, hKey);
9473 cm_msg(MERROR, "db_save_xml_key", "Long odb string array probably truncated, odb path \"%s\"[%d]", path.c_str(), i);
9474 }
9475 mxml_write_value(writer, str.c_str());
9476 }
9477
9478 mxml_end_element(writer);
9479 }
9480
9481 mxml_end_element(writer); /* keyarray */
9482 }
9483
9484 free(data);
9485 data = NULL;
9486 }
9487
9488 return DB_SUCCESS;
9489}
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 4544 of file odb.cxx.

4571{
4572 HNDLE hSubkey;
4573 KEY key;
4574 INT i, status;
4575
4577 if (status != DB_SUCCESS)
4578 return status;
4579
4580 status = callback(hDB, hKey, &key, level, info);
4581 if (status == 0)
4582 return status;
4583
4584 if (key.type == TID_KEY) {
4585 for (i = 0;; i++) {
4587
4588 if (!hSubkey)
4589 break;
4590
4591 db_scan_tree(hDB, hSubkey, level + 1, callback, info);
4592 }
4593 }
4594
4595 return DB_SUCCESS;
4596}
struct callback_addr callback
Definition mserver.cxx:22
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 4627 of file odb.cxx.

4655{
4656 HNDLE hSubkey;
4657 KEY key;
4658 INT i, status;
4659
4661 if (status != DB_SUCCESS)
4662 return status;
4663
4664 callback(hDB, hKey, &key, level, info);
4665
4666 if (key.type == TID_KEY) {
4667 for (i = 0;; i++) {
4669
4670 if (!hSubkey)
4671 break;
4672
4673 db_scan_tree_link(hDB, hSubkey, level + 1, callback, info);
4674 }
4675 }
4676
4677 return DB_SUCCESS;
4678}
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 4600 of file odb.cxx.

4601{
4602 assert(pkey != NULL);
4603
4604 if (level >= MAX_ODB_PATH) {
4605 db_msg(msg, MERROR, "db_scan_tree_locked", "Max ODB depth level %d exceeded", MAX_ODB_PATH);
4606 return DB_TRUNCATED;
4607 }
4608
4609 int status = callback(pheader, pkey, level, info, msg);
4610 if (status == 0)
4611 return status;
4612
4613 if (pkey->type == TID_KEY) {
4614 const KEY* subkey = db_enum_first_locked(pheader, pkey, msg);
4615 while (subkey != NULL) {
4616 db_scan_tree_locked(pheader, subkey, level + 1, callback, info, msg);
4617 subkey = db_enum_next_locked(pheader, pkey, subkey, msg);
4618 }
4619 }
4620
4621 return DB_SUCCESS;
4622}
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 14144 of file odb.cxx.

14145{
14146#ifdef LOCAL_ROUTINES
14147 MJsonNode* scl = MJsonNode::MakeObject();
14148 MJsonNode* clients = MJsonNode::MakeArray();
14149
14150 scl->AddToObject("now", MJsonNode::MakeNumber(ss_time_sec()));
14151 scl->AddToObject("clients", clients);
14152
14153 /* lock database */
14155
14156 DATABASE *pdb = &_database[hDB - 1];
14157 DATABASE_HEADER *pheader = pdb->database_header;
14158
14159 DWORD now = ss_millitime();
14160
14161 /* list clients */
14162 for (int i = 0; i < pheader->max_client_index; i++) {
14163 DATABASE_CLIENT *pclient = &pheader->client[i];
14164 if (pclient->pid) {
14165 MJsonNode* c = MJsonNode::MakeObject();
14166 c->AddToObject("slot", MJsonNode::MakeNumber(i));
14167 c->AddToObject("pid", MJsonNode::MakeNumber(pclient->pid));
14168 c->AddToObject("name", MJsonNode::MakeString(pclient->name));
14169 std::string path = msprintf("/System/Clients/%d/Host", pclient->pid);
14170 const KEY* pkey = db_find_pkey_locked(pheader, NULL, path.c_str(), true, NULL, NULL);
14171 if (pkey) {
14172 int host_size = pkey->total_size;
14173 char* host = (char*)malloc(host_size);
14174 assert(host != NULL);
14175 db_get_data_locked(pheader, pkey, 0, host, &host_size, TID_STRING, NULL);
14176 c->AddToObject("host", MJsonNode::MakeString(host));
14177 free(host);
14178 }
14179 c->AddToObject("watchdog_timeout_millisec", MJsonNode::MakeNumber(pclient->watchdog_timeout));
14180 // "now" and "last_activity" is millisecond time wrapped around at 32 bits, must do unsigned 32-bit math here, not in javascript
14181 c->AddToObject("last_activity_millisec", MJsonNode::MakeNumber(now - pclient->last_activity));
14182 clients->AddToArray(c);
14183 }
14184 }
14185
14187
14188 return scl;
14189#else
14190 return MJsonNode::MakeNull();
14191#endif
14192}
double ss_time_sec()
Definition system.cxx:3539
char c
Definition system.cxx:1312
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()
INT cm_connect_experiment(const char *host_name, const char *exp_name, const char *client_name, void(*func)(char *))
Definition midas.cxx:2294
INT cm_disconnect_experiment(void)
Definition midas.cxx:2862
INT cm_get_environment(char *host_name, int host_name_size, char *exp_name, int exp_name_size)
Definition midas.cxx:2150
#define CM_SUCCESS
Definition midas.h:582
BOOL ss_kbhit()
Definition system.cxx:3736
INT ss_getchar(BOOL reset)
Definition system.cxx:7581
std::string strcomb1(const char **list)
Definition odb.cxx:668
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.cxx:44
#define HOST_NAME_LENGTH
Definition midas.h:273
Returns
DB_SUCCESS

Definition at line 13809 of file odb.cxx.

13810{
13811 INT i;
13812
13813 for (i = 0; i < _record_list_entries; i++)
13814 if (_record_list[i].access_mode & MODE_WRITE) {
13815 if (memcmp(_record_list[i].copy, _record_list[i].data, _record_list[i].buf_size) != 0) {
13816 if (rpc_is_remote()) {
13817 int align = ss_get_struct_align();
13819 } else {
13821 }
13822 memcpy(_record_list[i].copy, _record_list[i].data, _record_list[i].buf_size);
13823 }
13824 }
13825
13826 return DB_SUCCESS;
13827}
#define RPC_NO_REPLY
Definition midas.h:396
#define RPC_DB_SET_RECORD
Definition mrpc.h:72
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 2440 of file odb.cxx.

2459{
2460 if (rpc_is_remote())
2461 return rpc_call(RPC_DB_SET_CLIENT_NAME, hDB, client_name);
2462
2463#ifdef LOCAL_ROUTINES
2464 {
2465 if (hDB > _database_entries || hDB <= 0) {
2466 cm_msg(MERROR, "db_set_client_name", "invalid database handle %d", hDB);
2467 return DB_INVALID_HANDLE;
2468 }
2469
2471
2472 DATABASE *pdb = &_database[hDB - 1];
2474 mstrlcpy(pclient->name, client_name, sizeof(pclient->name));
2475
2477 }
2478#endif /* LOCAL_ROUTINES */
2479
2480 return DB_SUCCESS;
2481}
#define RPC_DB_SET_CLIENT_NAME
Definition mrpc.h:77
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 7239 of file odb.cxx.

7240{
7241 if (rpc_is_remote())
7242 return rpc_call(RPC_DB_SET_DATA, hDB, hKey, data, buf_size, num_values, type);
7243
7244#ifdef LOCAL_ROUTINES
7245 {
7246 HNDLE hkeylink;
7247 int link_idx;
7248 int status;
7249
7250 if (hDB > _database_entries || hDB <= 0) {
7251 cm_msg(MERROR, "db_set_data", "invalid database handle");
7252 return DB_INVALID_HANDLE;
7253 }
7254
7255 if (!_database[hDB - 1].attached) {
7256 cm_msg(MERROR, "db_set_data", "invalid database handle");
7257 return DB_INVALID_HANDLE;
7258 }
7259
7260 if (hKey < (int) sizeof(DATABASE_HEADER)) {
7261 cm_msg(MERROR, "db_set_data", "invalid key handle");
7262 return DB_INVALID_HANDLE;
7263 }
7264
7265 if (num_values == 0)
7266 return DB_INVALID_PARAM;
7267
7269 db_err_msg* msg = NULL;
7270
7271
7272 DATABASE* pdb = &_database[hDB - 1];
7273 DATABASE_HEADER* pheader = pdb->database_header;
7274
7275 /* check if hKey argument is correct */
7276 if (!db_validate_hkey(pheader, hKey)) {
7278 return DB_INVALID_HANDLE;
7279 }
7280
7281 KEY* pkey = (KEY *) ((char *) pheader + hKey);
7282
7283 /* check for write access */
7284 if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
7286 return DB_NO_ACCESS;
7287 }
7288
7289 /* check for link to array index */
7290 if (pkey->type == TID_LINK) {
7291 char link_name[256]; // FIXME: use std::string
7292 mstrlcpy(link_name, (char *) pheader + pkey->data, sizeof(link_name));
7293 if (strlen(link_name) > 0 && link_name[strlen(link_name) - 1] == ']') {
7295 if (strchr(link_name, '[') == NULL)
7296 return DB_INVALID_LINK;
7297 link_idx = atoi(strchr(link_name, '[') + 1);
7298 *strchr(link_name, '[') = 0;
7299 if (db_find_key(hDB, 0, link_name, &hkeylink) != DB_SUCCESS)
7300 return DB_INVALID_LINK;
7301 return db_set_data_index(hDB, hkeylink, data, buf_size, link_idx, type);
7302 }
7303 }
7304
7305 status = db_check_set_data_locked(pheader, pkey, data, buf_size, num_values, type, "db_set_data", &msg);
7306
7307 if (status != DB_SUCCESS) {
7309 if (msg)
7310 db_flush_msg(&msg);
7311 return status;
7312 }
7313
7314 db_allow_write_locked(pdb, "db_set_data");
7315
7316 status = db_set_data_wlocked(pheader, pkey, data, buf_size, num_values, type, "db_set_data", &msg);
7317
7318 if (status != DB_SUCCESS) {
7320 if (msg)
7321 db_flush_msg(&msg);
7322 return status;
7323 }
7324
7325 db_notify_clients_locked(pdb, hKey, -1, TRUE, &msg);
7327 if (msg)
7328 db_flush_msg(&msg);
7329
7330
7331 }
7332#endif /* LOCAL_ROUTINES */
7333
7334 return DB_SUCCESS;
7335}
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:7125
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:7038
#define RPC_DB_SET_DATA
Definition mrpc.h:67
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 7337 of file odb.cxx.

7343{
7344 if (rpc_is_remote())
7345 return rpc_call(RPC_DB_SET_DATA1, hDB, hKey, data, buf_size, num_values, type);
7346
7347#ifdef LOCAL_ROUTINES
7348 {
7349 DATABASE_HEADER *pheader;
7350 KEY *pkey;
7351 HNDLE hkeylink;
7352 int link_idx;
7353 char link_name[256];
7354 int status;
7355
7356 if (hDB > _database_entries || hDB <= 0) {
7357 cm_msg(MERROR, "db_set_data1", "invalid database handle");
7358 return DB_INVALID_HANDLE;
7359 }
7360
7361 if (!_database[hDB - 1].attached) {
7362 cm_msg(MERROR, "db_set_data1", "invalid database handle");
7363 return DB_INVALID_HANDLE;
7364 }
7365
7366 if (hKey < (int) sizeof(DATABASE_HEADER)) {
7367 cm_msg(MERROR, "db_set_data1", "invalid key handle");
7368 return DB_INVALID_HANDLE;
7369 }
7370
7371 if (num_values == 0)
7372 return DB_INVALID_PARAM;
7373
7375 db_err_msg* msg = NULL;
7376
7377 pheader = _database[hDB - 1].database_header;
7378
7379 /* check if hKey argument is correct */
7380 if (!db_validate_hkey(pheader, hKey)) {
7382 return DB_INVALID_HANDLE;
7383 }
7384
7385 pkey = (KEY *) ((char *) pheader + hKey);
7386
7387 /* check for write access */
7388 if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
7390 return DB_NO_ACCESS;
7391 }
7392
7393 /* check for link to array index */
7394 if (pkey->type == TID_LINK) {
7395 mstrlcpy(link_name, (char *) pheader + pkey->data, sizeof(link_name));
7396 if (strlen(link_name) > 0 && link_name[strlen(link_name) - 1] == ']') {
7398 if (strchr(link_name, '[') == NULL)
7399 return DB_INVALID_LINK;
7400 link_idx = atoi(strchr(link_name, '[') + 1);
7401 *strchr(link_name, '[') = 0;
7402 if (db_find_key(hDB, 0, link_name, &hkeylink) != DB_SUCCESS)
7403 return DB_INVALID_LINK;
7404 return db_set_data_index1(hDB, hkeylink, data, buf_size, link_idx, type, FALSE);
7405 }
7406 }
7407
7408 status = db_check_set_data_locked(pheader, pkey, data, buf_size, num_values, type, "db_set_data1", &msg);
7409
7410 if (status != DB_SUCCESS) {
7412 if (msg)
7413 db_flush_msg(&msg);
7414 return status;
7415 }
7416
7417 db_allow_write_locked(&_database[hDB - 1], "db_set_data1");
7418
7419 status = db_set_data_wlocked(pheader, pkey, data, buf_size, num_values, type, "db_set_data1", &msg);
7420
7421 if (status != DB_SUCCESS) {
7423 if (msg)
7424 db_flush_msg(&msg);
7425 return status;
7426 }
7427
7429 if (msg)
7430 db_flush_msg(&msg);
7431
7432 }
7433#endif /* LOCAL_ROUTINES */
7434
7435 return DB_SUCCESS;
7436}
INT db_set_data_index1(HNDLE hDB, HNDLE hKey, const void *data, INT data_size, INT idx, DWORD type, BOOL bNotify)
Definition odb.cxx:7844
#define RPC_DB_SET_DATA1
Definition mrpc.h:96
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 7668 of file odb.cxx.

7669{
7670 if (rpc_is_remote())
7671 return rpc_call(RPC_DB_SET_DATA_INDEX, hDB, hKey, data, data_size, idx, type);
7672
7673#ifdef LOCAL_ROUTINES
7674 {
7675 int link_idx;
7676 HNDLE hkeylink;
7677 int status;
7678
7679 if (hDB > _database_entries || hDB <= 0) {
7680 cm_msg(MERROR, "db_set_data_index", "invalid database handle");
7681 return DB_INVALID_HANDLE;
7682 }
7683
7684 if (!_database[hDB - 1].attached) {
7685 cm_msg(MERROR, "db_set_data_index", "invalid database handle");
7686 return DB_INVALID_HANDLE;
7687 }
7688
7689 if (hKey < (int) sizeof(DATABASE_HEADER)) {
7690 cm_msg(MERROR, "db_set_data_index", "invalid key handle");
7691 return DB_INVALID_HANDLE;
7692 }
7693
7695 db_err_msg* msg = NULL;
7696
7697 DATABASE* pdb = &_database[hDB - 1];
7698 DATABASE_HEADER* pheader = pdb->database_header;
7699
7700 /* check if hKey argument is correct */
7701 if (!db_validate_hkey(pheader, hKey)) {
7703 return DB_INVALID_HANDLE;
7704 }
7705
7706 KEY* pkey = (KEY *) ((char *) pheader + hKey);
7707
7708 /* check for write access */
7709 if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
7711 return DB_NO_ACCESS;
7712 }
7713
7714 /* check for link to array index */
7715 if (pkey->type == TID_LINK) {
7716 char link_name[256]; // FIXME: use std::string
7717 mstrlcpy(link_name, (char *) pheader + pkey->data, sizeof(link_name));
7718 if (strlen(link_name) > 0 && link_name[strlen(link_name) - 1] == ']') {
7720 if (strchr(link_name, '[') == NULL)
7721 return DB_INVALID_LINK;
7722 link_idx = atoi(strchr(link_name, '[') + 1);
7723 *strchr(link_name, '[') = 0;
7724 if (db_find_key(hDB, 0, link_name, &hkeylink) != DB_SUCCESS)
7725 return DB_INVALID_LINK;
7726 return db_set_data_index(hDB, hkeylink, data, data_size, link_idx, type);
7727 }
7728 }
7729
7730 status = db_check_set_data_index_locked(pheader, pkey, idx, data, data_size, type, "db_set_data_index", &msg);
7731
7732 if (status != DB_SUCCESS) {
7734 if (msg)
7735 db_flush_msg(&msg);
7736 return status;
7737 }
7738
7739 db_allow_write_locked(&_database[hDB-1], "db_set_data_index");
7740
7741 status = db_set_data_index_wlocked(pheader, pkey, idx, data, data_size, type, "db_set_data_index", &msg);
7742
7743 if (status != DB_SUCCESS) {
7745 if (msg)
7746 db_flush_msg(&msg);
7747 return status;
7748 }
7749
7750 db_notify_clients_locked(pdb, hKey, idx, TRUE, &msg);
7752 if (msg)
7753 db_flush_msg(&msg);
7754
7755 }
7756#endif /* LOCAL_ROUTINES */
7757
7758 return DB_SUCCESS;
7759}
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:7081
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:7172
#define RPC_DB_SET_DATA_INDEX
Definition mrpc.h:68
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 7844 of file odb.cxx.

7871{
7872 if (rpc_is_remote())
7873 return rpc_call(RPC_DB_SET_DATA_INDEX1, hDB, hKey, data, data_size, idx, type, bNotify);
7874
7875#ifdef LOCAL_ROUTINES
7876 {
7877 if (hDB > _database_entries || hDB <= 0) {
7878 cm_msg(MERROR, "db_set_data_index1", "invalid database handle");
7879 return DB_INVALID_HANDLE;
7880 }
7881
7882 if (!_database[hDB - 1].attached) {
7883 cm_msg(MERROR, "db_set_data_index1", "invalid database handle");
7884 return DB_INVALID_HANDLE;
7885 }
7886
7887 if (hKey < (int) sizeof(DATABASE_HEADER)) {
7888 cm_msg(MERROR, "db_set_data_index1", "invalid key handle");
7889 return DB_INVALID_HANDLE;
7890 }
7891
7893 db_err_msg* msg = NULL;
7894
7895 DATABASE* pdb = &_database[hDB - 1];
7896 DATABASE_HEADER* pheader = pdb->database_header;
7897
7898 /* check if hKey argument is correct */
7899 if (!db_validate_hkey(pheader, hKey)) {
7901 return DB_INVALID_HANDLE;
7902 }
7903
7904 KEY* pkey = (KEY *) ((char *) pheader + hKey);
7905
7906 int status = db_check_set_data_index_locked(pheader, pkey, idx, data, data_size, type, "db_set_data_index1", &msg);
7907
7908 if (status != DB_SUCCESS) {
7910 if (msg)
7911 db_flush_msg(&msg);
7912 return status;
7913 }
7914
7915 db_allow_write_locked(pdb, "db_set_data_index1");
7916
7917 status = db_set_data_index_wlocked(pheader, pkey, idx, data, data_size, type, "db_set_data_index1", &msg);
7918
7919 if (status != DB_SUCCESS) {
7921 if (msg)
7922 db_flush_msg(&msg);
7923 return status;
7924 }
7925
7926 if (bNotify)
7927 db_notify_clients_locked(pdb, hKey, idx, TRUE, &msg);
7928
7930 if (msg)
7931 db_flush_msg(&msg);
7932
7933 }
7934#endif /* LOCAL_ROUTINES */
7935
7936 return DB_SUCCESS;
7937}
#define RPC_DB_SET_DATA_INDEX1
Definition mrpc.h:86
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 7081 of file odb.cxx.

7082{
7083 /* increase key size if necessary */
7084 if (idx >= pkey->num_values || pkey->item_size == 0) {
7085 // FIXME: validate pkey->data
7086 pkey->data = (POINTER_T) realloc_data(pheader, (char *) pheader + pkey->data, pkey->total_size, data_size * (idx + 1), caller);
7087
7088 if (pkey->data == 0) {
7089 pkey->total_size = 0;
7090 pkey->num_values = 0;
7091 db_msg(msg, MERROR, caller, "Cannot reallocate \"%s\" with new num_values %d and new size %d bytes, online database full", db_get_path_pkey(pheader, pkey).c_str(), idx + 1, data_size * (idx + 1));
7092 return DB_FULL;
7093 }
7094
7095 pkey->data -= (POINTER_T) pheader;
7096 if (!pkey->item_size)
7097 pkey->item_size = data_size;
7098 pkey->total_size = data_size * (idx + 1);
7099 pkey->num_values = idx + 1;
7100 }
7101
7102#if 0
7103 /* cut strings which are too long */
7104 if ((type == TID_STRING || type == TID_LINK) && (int) strlen((char *) data) + 1 > pkey->item_size)
7105 *((char *) data + pkey->item_size - 1) = 0;
7106
7107 /* copy data */
7108 memcpy((char *) pheader + pkey->data + idx * pkey->item_size, data, pkey->item_size);
7109#endif
7110
7111 if ((type == TID_STRING || type == TID_LINK)) {
7112 /* cut strings which are too long */
7113 mstrlcpy((char *) pheader + pkey->data + idx * pkey->item_size, (char*)data, pkey->item_size);
7114 } else {
7115 /* copy data */
7116 memcpy((char *) pheader + pkey->data + idx * pkey->item_size, data, pkey->item_size);
7117 }
7118
7119 /* update time */
7120 pkey->last_written = ss_time();
7121
7122 return DB_SUCCESS;
7123}
static void * realloc_data(DATABASE_HEADER *pheader, void *address, INT old_size, INT new_size, const char *caller)
Definition odb.cxx:597
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 7038 of file odb.cxx.

7039{
7040 /* if no buf_size given (Java!), calculate it */
7041 if (data_size == 0)
7042 data_size = pkey->item_size * num_values;
7043
7044 /* resize data size if necessary */
7045 if (pkey->total_size != data_size) {
7046 // FIXME: validate pkey->data!
7047 pkey->data = (POINTER_T) realloc_data(pheader, (char *) pheader + pkey->data, pkey->total_size, data_size, caller);
7048
7049 if (pkey->data == 0) {
7050 pkey->total_size = 0;
7051 db_msg(msg, MERROR, caller, "Cannot reallocate \"%s\" with new size %d bytes, online database full", db_get_path_pkey(pheader, pkey).c_str(), data_size);
7052 return DB_FULL;
7053 }
7054
7055 pkey->data -= (POINTER_T) pheader;
7056 pkey->total_size = data_size;
7057 }
7058
7059 /* set number of values */
7060 pkey->num_values = num_values;
7061
7062 if (type == TID_STRING || type == TID_LINK)
7063 pkey->item_size = data_size / num_values;
7064 else
7065 pkey->item_size = rpc_tid_size(type);
7066
7067 if ((type == TID_STRING || type == TID_LINK) && pkey->num_values == 1) {
7068 /* copy string up to NUL termination */
7069 mstrlcpy((char *) pheader + pkey->data, (const char*)data, data_size);
7070 } else {
7071 /* copy data */
7072 memcpy((char *) pheader + pkey->data, data, data_size);
7073 }
7074
7075 /* update time */
7076 pkey->last_written = ss_time();
7077
7078 return DB_SUCCESS;
7079}
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 7449 of file odb.cxx.

7450{
7451 if (rpc_is_remote())
7452 return rpc_call(RPC_DB_SET_LINK_DATA, hDB, hKey, data, buf_size, num_values, type);
7453
7454#ifdef LOCAL_ROUTINES
7455 {
7456 if (hDB > _database_entries || hDB <= 0) {
7457 cm_msg(MERROR, "db_set_data", "invalid database handle");
7458 return DB_INVALID_HANDLE;
7459 }
7460
7461 if (!_database[hDB - 1].attached) {
7462 cm_msg(MERROR, "db_set_data", "invalid database handle");
7463 return DB_INVALID_HANDLE;
7464 }
7465
7466 if (hKey < (int) sizeof(DATABASE_HEADER)) {
7467 cm_msg(MERROR, "db_set_data", "invalid key handle");
7468 return DB_INVALID_HANDLE;
7469 }
7470
7471 if (num_values == 0)
7472 return DB_INVALID_PARAM;
7473
7475 db_err_msg* msg = NULL;
7476
7477 DATABASE* pdb = &_database[hDB - 1];
7478 DATABASE_HEADER* pheader = pdb->database_header;
7479
7480 /* check if hKey argument is correct */
7481 if (!db_validate_hkey(pheader, hKey)) {
7483 return DB_INVALID_HANDLE;
7484 }
7485
7486 KEY* pkey = (KEY *) ((char *) pheader + hKey);
7487
7488 int status = db_check_set_data_locked(pheader, pkey, data, buf_size, num_values, type, "db_set_link_data", &msg);
7489
7490 if (status != DB_SUCCESS) {
7492 if (msg)
7493 db_flush_msg(&msg);
7494 return status;
7495 }
7496
7497 db_allow_write_locked(pdb, "db_set_link_data");
7498
7499 status = db_set_data_wlocked(pheader, pkey, data, buf_size, num_values, type, "db_set_link_data", &msg);
7500
7501 if (status != DB_SUCCESS) {
7503 if (msg)
7504 db_flush_msg(&msg);
7505 return status;
7506 }
7507
7508 db_notify_clients_locked(pdb, hKey, -1, TRUE, &msg);
7510 if (msg)
7511 db_flush_msg(&msg);
7512
7513 }
7514#endif /* LOCAL_ROUTINES */
7515
7516 return DB_SUCCESS;
7517}
#define RPC_DB_SET_LINK_DATA
Definition mrpc.h:94
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 7773 of file odb.cxx.

7774{
7775 if (rpc_is_remote())
7776 return rpc_call(RPC_DB_SET_LINK_DATA_INDEX, hDB, hKey, data, data_size, idx, type);
7777
7778#ifdef LOCAL_ROUTINES
7779 {
7780 if (hDB > _database_entries || hDB <= 0) {
7781 cm_msg(MERROR, "db_set_link_data_index", "invalid database handle");
7782 return DB_INVALID_HANDLE;
7783 }
7784
7785 if (!_database[hDB - 1].attached) {
7786 cm_msg(MERROR, "db_set_link_data_index", "invalid database handle");
7787 return DB_INVALID_HANDLE;
7788 }
7789
7790 if (hKey < (int) sizeof(DATABASE_HEADER)) {
7791 cm_msg(MERROR, "db_set_link_data_index", "invalid key handle");
7792 return DB_INVALID_HANDLE;
7793 }
7794
7796 db_err_msg* msg = NULL;
7797
7798 DATABASE* pdb = &_database[hDB - 1];
7799 DATABASE_HEADER* pheader = pdb->database_header;
7800
7801 /* check if hKey argument is correct */
7802 if (!db_validate_hkey(pheader, hKey)) {
7804 return DB_INVALID_HANDLE;
7805 }
7806
7807 KEY* pkey = (KEY *) ((char *) pheader + hKey);
7808
7809 int status = db_check_set_data_index_locked(pheader, pkey, idx, data, data_size, type, "db_set_link_data_index", &msg);
7810
7811 if (status != DB_SUCCESS) {
7813 if (msg)
7814 db_flush_msg(&msg);
7815 return status;
7816 }
7817
7818 db_allow_write_locked(pdb, "db_set_link_data_index");
7819
7820 status = db_set_data_index_wlocked(pheader, pkey, idx, data, data_size, type, "db_set_link_data_index", &msg);
7821
7822 if (status != DB_SUCCESS) {
7824 if (msg)
7825 db_flush_msg(&msg);
7826 return status;
7827 }
7828
7829 db_notify_clients_locked(pdb, hKey, idx, TRUE, &msg);
7831 if (msg)
7832 db_flush_msg(&msg);
7833
7834 }
7835#endif /* LOCAL_ROUTINES */
7836
7837 return DB_SUCCESS;
7838}
#define RPC_DB_SET_LINK_DATA_INDEX
Definition mrpc.h:95
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 2748 of file odb.cxx.

2749{
2750#ifdef LOCAL_ROUTINES
2751
2752 /* return zero if no ODB is open or we run remotely */
2753 if (_database_entries == 0)
2754 return 0;
2755
2756 if (hDB > _database_entries || hDB <= 0) {
2757 cm_msg(MERROR, "db_set_lock_timeout", "invalid database handle %d", hDB);
2758 return 0;
2759 }
2760
2761 if (timeout_millisec > 0) {
2762 _database[hDB - 1].timeout = timeout_millisec;
2763 }
2764
2765 return _database[hDB - 1].timeout;
2766#else
2767 return 0;
2768#endif
2769}
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 8040 of file odb.cxx.

8065{
8066 if (rpc_is_remote())
8067 return rpc_call(RPC_DB_SET_MODE, hDB, hKey, mode, recurse);
8068
8069#ifdef LOCAL_ROUTINES
8070 {
8071 DATABASE_HEADER *pheader;
8072 BOOL locked = FALSE;
8073
8074 if (hDB > _database_entries || hDB <= 0) {
8075 cm_msg(MERROR, "db_set_mode", "invalid database handle");
8076 return DB_INVALID_HANDLE;
8077 }
8078
8079 if (!_database[hDB - 1].attached) {
8080 cm_msg(MERROR, "db_set_mode", "invalid database handle");
8081 return DB_INVALID_HANDLE;
8082 }
8083
8084 if (recurse < 2) {
8086 locked = TRUE;
8087 }
8088
8089 pheader = _database[hDB - 1].database_header;
8090
8091 db_err_msg* msg = NULL;
8092 int status = 0;
8093
8094 KEY *pkey = (KEY*)db_get_pkey(pheader, hKey, &status, "db_set_mode", &msg);
8095
8096 if (!pkey) {
8097 if (locked) {
8099 if (msg)
8100 db_flush_msg(&msg);
8101 return status;
8102 }
8103 }
8104
8105 db_allow_write_locked(&_database[hDB-1], "db_set_mode");
8106
8107 status = db_set_mode_wlocked(pheader, pkey, mode, recurse, &msg);
8108
8109 if (locked) {
8111 if (msg)
8112 db_flush_msg(&msg);
8113 }
8114
8115 return status;
8116 }
8117#endif /* LOCAL_ROUTINES */
8118
8119 return DB_SUCCESS;
8120}
#define RPC_DB_SET_MODE
Definition mrpc.h:69
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 7992 of file odb.cxx.

8012{
8013 /* resolve links */
8014 if (pkey->type == TID_LINK) {
8015 int status;
8016 pkey = (KEY*)db_resolve_link_locked(pheader, pkey, &status, msg);
8017 if (!pkey) {
8018 return status;
8019 }
8020 }
8021
8022 if (pkey->type == TID_KEY && recurse) {
8023 // drop "const" from KEY* we are permitted to write to ODB!
8024 KEY* psubkey = (KEY*)db_enum_first_locked(pheader, pkey, msg);
8025 while (psubkey) {
8026 db_set_mode_wlocked(pheader, psubkey, mode, recurse+1, msg);
8027 psubkey = (KEY*)db_enum_next_locked(pheader, pkey, psubkey, msg);
8028 }
8029 }
8030
8031 /* now set mode */
8032 pkey->access_mode = mode;
8033
8034 return DB_SUCCESS;
8035}
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 7523 of file odb.cxx.

7543{
7544 if (rpc_is_remote())
7545 return rpc_call(RPC_DB_SET_NUM_VALUES, hDB, hKey, num_values);
7546
7547#ifdef LOCAL_ROUTINES
7548 {
7549 INT new_size;
7550
7551 if (hDB > _database_entries || hDB <= 0) {
7552 cm_msg(MERROR, "db_set_num_values", "invalid database handle");
7553 return DB_INVALID_HANDLE;
7554 }
7555
7556 if (!_database[hDB - 1].attached) {
7557 cm_msg(MERROR, "db_set_num_values", "invalid database handle");
7558 return DB_INVALID_HANDLE;
7559 }
7560
7561 if (hKey < (int) sizeof(DATABASE_HEADER)) {
7562 cm_msg(MERROR, "db_set_num_values", "invalid key handle");
7563 return DB_INVALID_HANDLE;
7564 }
7565
7566 if (num_values <= 0) {
7567 cm_msg(MERROR, "db_set_num_values", "invalid num_values %d", num_values);
7568 return DB_INVALID_PARAM;
7569 }
7570
7571 if (num_values == 0)
7572 return DB_INVALID_PARAM;
7573
7575 db_err_msg* msg = NULL;
7576
7577 DATABASE* pdb = &_database[hDB - 1];
7578 DATABASE_HEADER* pheader = pdb->database_header;
7579
7580 /* check if hKey argument is correct */
7581 if (!db_validate_hkey(pheader, hKey)) {
7583 return DB_INVALID_HANDLE;
7584 }
7585
7586 KEY* pkey = (KEY *) ((char *) pheader + hKey);
7587
7588 /* check for write access */
7589 if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
7591 return DB_NO_ACCESS;
7592 }
7593
7594 /* keys cannot contain data */
7595 if (pkey->type == TID_KEY) {
7597 cm_msg(MERROR, "db_set_num_values", "Key cannot contain data");
7598 return DB_TYPE_MISMATCH;
7599 }
7600
7601 if (pkey->total_size != pkey->item_size * pkey->num_values) {
7603 cm_msg(MERROR, "db_set_num_values", "Corrupted key");
7604 return DB_CORRUPTED;
7605 }
7606
7607 if (pkey->item_size == 0) {
7609 cm_msg(MERROR, "db_set_num_values", "Cannot resize array with item_size equal to zero");
7610 return DB_INVALID_PARAM;
7611 }
7612
7613 db_allow_write_locked(pdb, "db_set_num_values");
7614
7615 /* resize data size if necessary */
7616 if (pkey->num_values != num_values) {
7617 new_size = pkey->item_size * num_values;
7618
7619 pkey->data = (POINTER_T) realloc_data(pheader, (char *) pheader + pkey->data, pkey->total_size, new_size, "db_set_num_values");
7620
7621 if (pkey->data == 0) {
7622 pkey->total_size = 0;
7623 pkey->num_values = 0;
7624 db_msg(&msg, MERROR, "db_set_num_values", "Cannot resize \"%s\" with num_values %d and new size %d bytes, online database full", db_get_path_pkey(pheader, pkey).c_str(), num_values, new_size);
7626 if (msg)
7627 db_flush_msg(&msg);
7628 return DB_FULL;
7629 }
7630
7631 pkey->data -= (POINTER_T) pheader;
7632 pkey->total_size = new_size;
7633 pkey->num_values = num_values;
7634 }
7635
7636 /* update time */
7637 pkey->last_written = ss_time();
7638
7639 db_notify_clients_locked(pdb, hKey, -1, TRUE, &msg);
7641 if (msg)
7642 db_flush_msg(&msg);
7643
7644 }
7645#endif /* LOCAL_ROUTINES */
7646
7647 return DB_SUCCESS;
7648}
#define RPC_DB_SET_NUM_VALUES
Definition mrpc.h:89
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
HNDLE hKeyst
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 12320 of file odb.cxx.

12321{
12322 if (rpc_is_remote()) {
12323 align = ss_get_struct_align();
12324 return rpc_call(RPC_DB_SET_RECORD, hDB, hKey, data, buf_size, align);
12325 }
12326#ifdef LOCAL_ROUTINES
12327 {
12328 KEY key;
12329 INT convert_flags;
12330 INT total_size;
12331 void *pdata;
12332
12333 convert_flags = 0;
12334
12335 if (!align)
12336 align = ss_get_struct_align();
12337 else {
12338 /* only convert data if called remotely, as indicated by align != 0 */
12339 if (rpc_is_mserver()) {
12340 convert_flags = rpc_get_convert_flags();
12341 }
12342 }
12343
12344 /* check if key has subkeys */
12345 db_get_key(hDB, hKey, &key);
12346 if (key.type != TID_KEY) {
12347 /* copy single key */
12348 if (key.item_size * key.num_values != buf_size) {
12349 cm_msg(MERROR, "db_set_record", "struct size mismatch for \"%s\"", key.name);
12351 }
12352
12353 if (convert_flags) {
12354 if (key.num_values > 1)
12356 else
12357 rpc_convert_single(data, key.type, 0, convert_flags);
12358 }
12359
12361 return DB_SUCCESS;
12362 }
12363
12364 /* check record size */
12365 db_get_record_size(hDB, hKey, align, &total_size);
12366 if (total_size != buf_size) {
12367 cm_msg(MERROR, "db_set_record", "struct size mismatch for \"%s\"", key.name);
12369 }
12370
12371 /* set subkey data */
12372 pdata = data;
12373 total_size = 0;
12374
12376 db_err_msg* msg = NULL;
12377 DATABASE *pdb = &_database[hDB - 1];
12378 db_allow_write_locked(pdb, "db_set_record");
12379 db_recurse_record_tree_locked(pdb, hKey, &pdata, &total_size, align, NULL, TRUE, convert_flags, &msg);
12381 if (msg)
12382 db_flush_msg(&msg);
12383 }
12384#endif /* LOCAL_ROUTINES */
12385
12386 return DB_SUCCESS;
12387}
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 5028 of file odb.cxx.

5030{
5031 if (rpc_is_remote())
5032 return rpc_call(RPC_DB_SET_VALUE, hDB, hKeyRoot, key_name, data, data_size, num_values, type);
5033
5034#ifdef LOCAL_ROUTINES
5035 {
5036 INT status;
5037
5038 if (num_values == 0)
5039 return DB_INVALID_PARAM;
5040
5042
5043 DATABASE* pdb = &_database[hDB - 1];
5044 DATABASE_HEADER* pheader = pdb->database_header;
5045
5046 db_allow_write_locked(pdb, "db_set_value");
5047
5048 db_err_msg* msg = NULL;
5049
5050 KEY* pkey_root = (KEY*)db_get_pkey(pheader, hKeyRoot, &status, "db_set_value", &msg);
5051
5052 if (pkey_root) {
5053 status = db_set_value_wlocked(pdb, pkey_root, key_name, data, data_size, num_values, type, &msg);
5054 }
5055
5057 if (msg)
5058 db_flush_msg(&msg);
5059
5060 return status;
5061 }
5062#endif /* LOCAL_ROUTINES */
5063
5064 return DB_SUCCESS;
5065}
#define RPC_DB_SET_VALUE
Definition mrpc.h:58
Here is the call 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:5135
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 5135 of file odb.cxx.

5137{
5138 int status;
5139 HNDLE hkey;
5140
5141 status = db_find_key(hDB, hKeyRoot, key_name, &hkey);
5142 if (!hkey) {
5143 status = db_create_key(hDB, hKeyRoot, key_name, type);
5144 status = db_find_key(hDB, hKeyRoot, key_name, &hkey);
5145 if (status != DB_SUCCESS)
5146 return status;
5147 } else
5148 if (trunc) {
5149 status = db_set_num_values(hDB, hkey, idx + 1);
5150 if (status != DB_SUCCESS)
5151 return status;
5152 }
5153
5154 return db_set_data_index(hDB, hkey, data, data_size, idx, type);
5155}
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 14038 of file odb.cxx.

14039{
14040 assert(s != NULL);
14041 int size = s->length() + 1; // 1 byte for final \0
14042 //printf("db_set_value_string: key_name [%s], string [%s], size %d\n", key_name, s->c_str(), size);
14043 return db_set_value(hDB, hKeyRoot, key_name, s->c_str(), size, 1, TID_STRING);
14044}
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 pdb,
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 5068 of file odb.cxx.

5069{
5070 INT status;
5071
5072 if (num_values == 0)
5073 return DB_INVALID_PARAM;
5074
5075 DATABASE_HEADER* pheader = pdb->database_header;
5076
5077 KEY* pkey = (KEY*)db_find_pkey_locked(pheader, pkey_root, key_name, true, &status, msg);
5078
5079 if (!pkey) {
5080 status = db_create_key_wlocked(pheader, pkey_root, key_name, type, &pkey, msg);
5081 if (status != DB_SUCCESS && status != DB_CREATED)
5082 return status;
5083 }
5084
5085 if (data_size == 0) {
5086 db_msg(msg, MERROR, "db_set_value", "zero data size not allowed");
5087 return DB_TYPE_MISMATCH;
5088 }
5089
5090 if (type != TID_STRING && type != TID_LINK && data_size != rpc_tid_size(type) * num_values) {
5091 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);
5092 return DB_TYPE_MISMATCH;
5093 }
5094
5095 status = db_check_set_data_locked(pheader, pkey, data, data_size, num_values, type, "db_set_value", msg);
5096
5097 if (status != DB_SUCCESS)
5098 return status;
5099
5100 status = db_set_data_wlocked(pheader, pkey, data, data_size, num_values, type, "db_set_value", msg);
5101
5102 if (status != DB_SUCCESS)
5103 return status;
5104
5105 db_notify_clients_locked(pdb, db_pkey_to_hkey(pheader, pkey), -1, TRUE, msg);
5106
5107 return DB_SUCCESS;
5108}
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 3060 of file odb.cxx.

3061{
3062 /* set watchdog flag of all open databases */
3063 for (int i = _database_entries; i > 0; i--) {
3064
3066
3067 DATABASE* pdb = &_database[i - 1];
3068
3069 if (!pdb->attached) {
3071 continue;
3072 }
3073
3075
3076 db_allow_write_locked(pdb, "db_set_watchdog_params");
3077
3078 /* clear entry from client structure in buffer header */
3079 pclient->watchdog_timeout = timeout;
3080
3081 /* show activity */
3082 pclient->last_activity = ss_millitime();
3083
3085 }
3086}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_show_mem()

std::string db_show_mem ( HNDLE  hDB,
BOOL  verbose 
)

Definition at line 704 of file odb.cxx.

705{
706 std::string buf;
707
708 int status;
709
710 DATABASE* pdb = db_lock_database(hDB, &status, "db_show_mem");
711
712 if (!pdb)
713 return "(Cannot lock ODB)";
714
715 db_err_msg *msg = NULL;
716
717 const DATABASE_HEADER *pheader = pdb->database_header;
718
719 buf += msprintf("Database header size is %9zu (0x%08X), all following values are offset by this!\n", sizeof(DATABASE_HEADER), (int)sizeof(DATABASE_HEADER));
720 buf += msprintf("Key area 0x00000000 - 0x%08X, size %d bytes\n", pheader->key_size - 1, pheader->key_size);
721 buf += msprintf("Data area 0x%08X - 0x%08X, size %d bytes\n\n", pheader->key_size, pheader->key_size + pheader->data_size, pheader->data_size);
722 buf += "\n";
723 buf += "Keylist:\n";
724 buf += "--------\n";
725
726 int total_size_key = 0;
727
728 if (!db_validate_key_offset(pheader, pheader->first_free_key)) {
729 db_unlock_database(pdb, "db_show_mem");
730 buf += "ODB is corrupted: pheader->first_free_key is invalid\n";
731 return buf;
732 }
733
734 FREE_DESCRIP *pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_key);
735
736 while ((POINTER_T) pfree != (POINTER_T) pheader) {
737 total_size_key += pfree->size;
738 buf += msprintf("Free block at %9d, size %9d, next %9d\n",
739 (int) ((POINTER_T) pfree - (POINTER_T) pheader - sizeof(DATABASE_HEADER)),
740 pfree->size, pfree->next_free ? (int) (pfree->next_free - sizeof(DATABASE_HEADER)) : 0);
741 if (!db_validate_key_offset(pheader, pfree->next_free)) {
742 buf += "ODB is corrupted: next_free is invalid!";
743 break;
744 }
745 pfree = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
746 }
747
748 buf += "\n";
749 buf += msprintf("Free Key area: %d bytes out of %d bytes\n", total_size_key, pheader->key_size);
750 buf += "\n";
751 buf += "Data:";
752 buf += "-----\n";
753
754 int total_size_data = 0;
755
756 if (!db_validate_data_offset(pheader, pheader->first_free_data)) {
757 db_unlock_database(pdb, "db_show_mem");
758 buf += "ODB is corrupted: pheader->first_free_data is invalid\n";
759 return buf;
760 }
761
762 pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_data);
763
764 while ((POINTER_T) pfree != (POINTER_T) pheader) {
765 total_size_data += pfree->size;
766 buf += msprintf("Free block at %9d, size %9d, next %9d\n",
767 (int) ((POINTER_T) pfree - (POINTER_T) pheader - sizeof(DATABASE_HEADER)),
768 pfree->size, pfree->next_free ? (int) (pfree->next_free - sizeof(DATABASE_HEADER)) : 0);
769 if (!db_validate_data_offset(pheader, pfree->next_free)) {
770 buf += "ODB is corrupted: next_free is invalid!";
771 break;
772 }
773 pfree = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
774 }
775
776 buf += "\n";
777 buf += msprintf("Free Data area: %d bytes out of %d bytes\n", total_size_data, pheader->data_size);
778 buf += "\n";
779 buf += msprintf("Free: %1d (%1.1lf%%) keylist, %1d (%1.1lf%%) data\n",
780 total_size_key,
781 100 * (double) total_size_key / pheader->key_size,
782 total_size_data, 100 * (double) total_size_data / pheader->data_size);
783
784 if (verbose) {
785 const KEY* proot = db_get_pkey(pheader, 0, 0, "db_show_mem", &msg);
786
787 if (proot) {
788 buf += "\n";
789 buf += "\n";
790 buf += " Key Data Size\n";
791 buf += "-----------------------------\n";
792 db_scan_tree_locked(pheader, proot, 0, print_key_info_locked, &buf, &msg);
793 buf += "-----------------------------\n";
794 buf += " Key Data Size\n";
795 }
796 }
797
798 buf += "\n";
799 buf += msprintf("Total ODB size: %d (0x%08X) Bytes, %lg MBytes\n",
800 pheader->key_size + pheader->data_size, pheader->key_size + pheader->data_size,
801 ((pheader->key_size + pheader->data_size) / 1E6));
802
803 db_unlock_database(pdb, "db_show_mem");
804
805 if (msg)
806 db_flush_msg(&msg);
807
808 return buf;
809}
static INT print_key_info_locked(const DATABASE_HEADER *pheader, const KEY *pkey, INT level, void *info, db_err_msg **msg)
Definition odb.cxx:685
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 14194 of file odb.cxx.

14195{
14196 //printf("db_sor(%s)\n", root_path);
14197 assert(root_path != NULL);
14198#ifdef LOCAL_ROUTINES
14199 size_t root_path_len = strlen(root_path);
14200 MJsonNode* sor = MJsonNode::MakeArray();
14201
14202 /* lock database */
14204
14205 DATABASE *pdb = &_database[hDB - 1];
14206 DATABASE_HEADER *pheader = pdb->database_header;
14207
14208 /* list clients */
14209 for (int i = 0; i < pheader->max_client_index; i++) {
14210 DATABASE_CLIENT *pclient = &pheader->client[i];
14211 if (pclient->pid) {
14212 for (int j = 0; j < pclient->max_index; j++) {
14213 std::string path = db_get_path_locked(pheader, pclient->open_record[j].handle);
14214 if (path.length() < root_path_len)
14215 continue;
14216 if (strncmp(root_path, path.c_str(), root_path_len) != 0)
14217 continue;
14218 MJsonNode* c = MJsonNode::MakeObject();
14219 c->AddToObject("name", MJsonNode::MakeString(pclient->name));
14220 //c->AddToObject("handle", MJsonNode::MakeNumber(pclient->open_record[j].handle));
14221 c->AddToObject("access_mode", MJsonNode::MakeNumber(pclient->open_record[j].access_mode));
14222 c->AddToObject("flags", MJsonNode::MakeNumber(pclient->open_record[j].flags));
14223 c->AddToObject("path", MJsonNode::MakeString(path.c_str()));
14224 sor->AddToArray(c);
14225 }
14226 }
14227 }
14228
14230
14231 return sor;
14232#else
14233 return MJsonNode::MakeNull();
14234#endif
14235}
WORD flags
Definition msystem.h:413
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 10865 of file odb.cxx.

10866{
10867 if (data_size == 0)
10868 sprintf(string, "<NULL>");
10869 else
10870 switch (type) {
10871 case TID_UINT8:
10872 sprintf(string, "%d", *(((BYTE *) data) + idx));
10873 break;
10874 case TID_INT8:
10875 sprintf(string, "%d", *(((char *) data) + idx));
10876 break;
10877 case TID_CHAR:
10878 sprintf(string, "%c", *(((char *) data) + idx));
10879 break;
10880 case TID_UINT16:
10881 sprintf(string, "%u", *(((WORD *) data) + idx));
10882 break;
10883 case TID_INT16:
10884 sprintf(string, "%d", *(((short *) data) + idx));
10885 break;
10886 case TID_UINT32:
10887 sprintf(string, "%u", *(((DWORD *) data) + idx));
10888 break;
10889 case TID_INT32:
10890 sprintf(string, "%d", *(((INT *) data) + idx));
10891 break;
10892 case TID_UINT64:
10893 sprintf(string, "%llu", *(((UINT64 *) data) + idx));
10894 break;
10895 case TID_INT64:
10896 sprintf(string, "%lld", *(((INT64 *) data) + idx));
10897 break;
10898 case TID_BOOL:
10899 sprintf(string, "%c", *(((BOOL *) data) + idx) ? 'y' : 'n');
10900 break;
10901 case TID_FLOAT:
10902 if (ss_isnan(*(((float *) data) + idx)))
10903 sprintf(string, "NAN");
10904 else
10905 sprintf(string, "%.7g", *(((float *) data) + idx));
10906 break;
10907 case TID_DOUBLE:
10908 if (ss_isnan(*(((double *) data) + idx)))
10909 sprintf(string, "NAN");
10910 else
10911 sprintf(string, "%.16lg", *(((double *) data) + idx));
10912 break;
10913 case TID_BITFIELD:
10914 sprintf(string, "%u", *(((DWORD *) data) + idx));
10915 break;
10916 case TID_STRING:
10917 case TID_LINK:
10918 mstrlcpy(string, ((char *) data) + data_size * idx, MAX_STRING_LENGTH);
10919 break;
10920 default:
10921 sprintf(string, "<unknown>");
10922 break;
10923 }
10924
10925 return DB_SUCCESS;
10926}
unsigned char BYTE
Definition mcstd.h:48
int ss_isnan(double x)
Definition system.cxx:8039
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 11109 of file odb.cxx.

11110{
11111 if (data_size == 0) {
11112 return "<NULL>";
11113 } else {
11114 char buf[256];
11115 switch (type) {
11116 case TID_UINT8:
11117 sprintf(buf, "%d", *(((BYTE *) data) + idx));
11118 return buf;
11119 case TID_INT8:
11120 sprintf(buf, "%d", *(((char *) data) + idx));
11121 return buf;
11122 case TID_CHAR:
11123 sprintf(buf, "%c", *(((char *) data) + idx));
11124 return buf;
11125 case TID_UINT16:
11126 sprintf(buf, "%u", *(((WORD *) data) + idx));
11127 return buf;
11128 case TID_INT16:
11129 sprintf(buf, "%d", *(((short *) data) + idx));
11130 return buf;
11131 case TID_UINT32:
11132 sprintf(buf, "%u", *(((DWORD *) data) + idx));
11133 return buf;
11134 case TID_INT32:
11135 sprintf(buf, "%d", *(((INT *) data) + idx));
11136 return buf;
11137 case TID_UINT64:
11138 sprintf(buf, "%llu", *(((UINT64 *) data) + idx));
11139 return buf;
11140 case TID_INT64:
11141 sprintf(buf, "%lld", *(((INT64 *) data) + idx));
11142 return buf;
11143 case TID_BOOL:
11144 sprintf(buf, "%c", *(((BOOL *) data) + idx) ? 'y' : 'n');
11145 return buf;
11146 case TID_FLOAT:
11147 if (ss_isnan(*(((float *) data) + idx))) {
11148 return "NAN";
11149 } else {
11150 sprintf(buf, "%.7g", *(((float *) data) + idx));
11151 return buf;
11152 }
11153 case TID_DOUBLE:
11154 if (ss_isnan(*(((double *) data) + idx))) {
11155 return "NAN";
11156 } else {
11157 sprintf(buf, "%.16lg", *(((double *) data) + idx));
11158 return buf;
11159 }
11160 case TID_BITFIELD:
11161 sprintf(buf, "%u", *(((DWORD *) data) + idx));
11162 return buf;
11163 case TID_STRING:
11164 case TID_LINK:
11165 return (((char *) data) + data_size * idx);
11166 default:
11167 return "<unknown>";
11168 }
11169 }
11170}
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 10941 of file odb.cxx.

10942{
10943 if (data_size == 0)
10944 sprintf(string, "<NULL>");
10945 else
10946 switch (type) {
10947 case TID_UINT8:
10948 sprintf(string, format, *(((BYTE *) data) + idx));
10949 break;
10950 case TID_INT8:
10951 sprintf(string, format, *(((char *) data) + idx));
10952 break;
10953 case TID_CHAR:
10954 sprintf(string, format, *(((char *) data) + idx));
10955 break;
10956 case TID_UINT16:
10957 sprintf(string, format, *(((WORD *) data) + idx));
10958 break;
10959 case TID_INT16:
10960 sprintf(string, format, *(((short *) data) + idx));
10961 break;
10962 case TID_UINT32:
10963 sprintf(string, format, *(((DWORD *) data) + idx));
10964 break;
10965 case TID_INT32:
10966 sprintf(string, format, *(((INT *) data) + idx));
10967 break;
10968 case TID_UINT64:
10969 sprintf(string, format, *(((UINT64 *) data) + idx));
10970 break;
10971 case TID_INT64:
10972 sprintf(string, format, *(((INT64 *) data) + idx));
10973 break;
10974 case TID_BOOL:
10975 sprintf(string, format, *(((BOOL *) data) + idx) ? 'y' : 'n');
10976 break;
10977 case TID_FLOAT:
10978 if (ss_isnan(*(((float *) data) + idx)))
10979 sprintf(string, "NAN");
10980 else
10981 sprintf(string, format, *(((float *) data) + idx));
10982 break;
10983 case TID_DOUBLE:
10984 if (ss_isnan(*(((double *) data) + idx)))
10985 sprintf(string, "NAN");
10986 else
10987 sprintf(string, format, *(((double *) data) + idx));
10988 break;
10989 case TID_BITFIELD:
10990 sprintf(string, format, *(((DWORD *) data) + idx));
10991 break;
10992 case TID_STRING:
10993 case TID_LINK:
10994 mstrlcpy(string, ((char *) data) + data_size * idx, MAX_STRING_LENGTH);
10995 break;
10996 default:
10997 sprintf(string, "<unknown>");
10998 break;
10999 }
11000
11001 return DB_SUCCESS;
11002}
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 11185 of file odb.cxx.

11186{
11187 if (data_size == 0) {
11188 return "<NULL>";
11189 } else {
11190 char buf[256];
11191 switch (type) {
11192 case TID_UINT8:
11193 sprintf(buf, format, *(((BYTE *) data) + idx));
11194 return buf;
11195 case TID_INT8:
11196 sprintf(buf, format, *(((char *) data) + idx));
11197 return buf;
11198 case TID_CHAR:
11199 sprintf(buf, format, *(((char *) data) + idx));
11200 return buf;
11201 case TID_UINT16:
11202 sprintf(buf, format, *(((WORD *) data) + idx));
11203 return buf;
11204 case TID_INT16:
11205 sprintf(buf, format, *(((short *) data) + idx));
11206 return buf;
11207 case TID_UINT32:
11208 sprintf(buf, format, *(((DWORD *) data) + idx));
11209 return buf;
11210 case TID_INT32:
11211 sprintf(buf, format, *(((INT *) data) + idx));
11212 return buf;
11213 case TID_UINT64:
11214 sprintf(buf, format, *(((UINT64 *) data) + idx));
11215 return buf;
11216 case TID_INT64:
11217 sprintf(buf, format, *(((INT64 *) data) + idx));
11218 return buf;
11219 case TID_BOOL:
11220 sprintf(buf, format, *(((BOOL *) data) + idx) ? 'y' : 'n');
11221 return buf;
11222 case TID_FLOAT:
11223 if (ss_isnan(*(((float *) data) + idx))) {
11224 return "NAN";
11225 } else {
11226 sprintf(buf, format, *(((float *) data) + idx));
11227 return buf;
11228 }
11229 case TID_DOUBLE:
11230 if (ss_isnan(*(((double *) data) + idx))) {
11231 return "NAN";
11232 } else {
11233 sprintf(buf, format, *(((double *) data) + idx));
11234 return buf;
11235 }
11236 case TID_BITFIELD:
11237 sprintf(buf, format, *(((DWORD *) data) + idx));
11238 return buf;
11239 case TID_STRING:
11240 case TID_LINK:
11241 return (((char *) data) + data_size * idx);
11242 default:
11243 return "<unknown>";
11244 }
11245 }
11246}
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 11005 of file odb.cxx.

11026{
11027 if (data_size == 0)
11028 sprintf(string, "<NULL>");
11029 else
11030 switch (type) {
11031 case TID_UINT8:
11032 sprintf(string, "0x%X", *(((BYTE *) data) + idx));
11033 break;
11034 case TID_INT8:
11035 sprintf(string, "0x%X", *(((char *) data) + idx));
11036 break;
11037 case TID_CHAR:
11038 sprintf(string, "%c", *(((char *) data) + idx));
11039 break;
11040 case TID_UINT16:
11041 sprintf(string, "0x%X", *(((WORD *) data) + idx));
11042 break;
11043 case TID_INT16:
11044 sprintf(string, "0x%hX", *(((short *) data) + idx));
11045 break;
11046 case TID_UINT32:
11047 sprintf(string, "0x%X", *(((DWORD *) data) + idx));
11048 break;
11049 case TID_INT32:
11050 sprintf(string, "0x%X", *(((INT *) data) + idx));
11051 break;
11052 case TID_UINT64:
11053 sprintf(string, "0x%llX", *(((UINT64 *) data) + idx));
11054 break;
11055 case TID_INT64:
11056 sprintf(string, "0x%llX", *(((INT64 *) data) + idx));
11057 break;
11058 case TID_BOOL:
11059 sprintf(string, "%c", *(((BOOL *) data) + idx) ? 'y' : 'n');
11060 break;
11061 case TID_FLOAT:
11062 if (ss_isnan(*(((float *) data) + idx)))
11063 sprintf(string, "NAN");
11064 else
11065 sprintf(string, "%.7g", *(((float *) data) + idx));
11066 break;
11067 case TID_DOUBLE:
11068 if (ss_isnan(*(((double *) data) + idx)))
11069 sprintf(string, "NAN");
11070 else
11071 sprintf(string, "%.16lg", *(((double *) data) + idx));
11072 break;
11073 case TID_BITFIELD:
11074 sprintf(string, "0x%X", *(((DWORD *) data) + idx));
11075 break;
11076 case TID_STRING:
11077 case TID_LINK:
11078 sprintf(string, "%s", ((char *) data) + data_size * idx);
11079 break;
11080 default:
11081 sprintf(string, "<unknown>");
11082 break;
11083 }
11084
11085 return DB_SUCCESS;
11086}
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 11252 of file odb.cxx.

11273{
11274 if (data_size == 0) {
11275 return "<NULL>";
11276 } else {
11277 char buf[256];
11278 switch (type) {
11279 case TID_UINT8:
11280 sprintf(buf, "0x%X", *(((BYTE *) data) + idx));
11281 return buf;
11282 case TID_INT8:
11283 sprintf(buf, "0x%X", *(((char *) data) + idx));
11284 return buf;
11285 case TID_CHAR:
11286 sprintf(buf, "%c", *(((char *) data) + idx));
11287 return buf;
11288 case TID_UINT16:
11289 sprintf(buf, "0x%X", *(((WORD *) data) + idx));
11290 return buf;
11291 case TID_INT16:
11292 sprintf(buf, "0x%hX", *(((short *) data) + idx));
11293 return buf;
11294 case TID_UINT32:
11295 sprintf(buf, "0x%X", *(((DWORD *) data) + idx));
11296 return buf;
11297 case TID_INT32:
11298 sprintf(buf, "0x%X", *(((INT *) data) + idx));
11299 return buf;
11300 case TID_UINT64:
11301 sprintf(buf, "0x%llX", *(((UINT64 *) data) + idx));
11302 return buf;
11303 case TID_INT64:
11304 sprintf(buf, "0x%llX", *(((INT64 *) data) + idx));
11305 return buf;
11306 case TID_BOOL:
11307 sprintf(buf, "%c", *(((BOOL *) data) + idx) ? 'y' : 'n');
11308 return buf;
11309 case TID_FLOAT:
11310 if (ss_isnan(*(((float *) data) + idx))) {
11311 return "NAN";
11312 } else {
11313 sprintf(buf, "%.7g", *(((float *) data) + idx));
11314 return buf;
11315 }
11316 case TID_DOUBLE:
11317 if (ss_isnan(*(((double *) data) + idx))) {
11318 return "NAN";
11319 } else {
11320 sprintf(buf, "%.16lg", *(((double *) data) + idx));
11321 return buf;
11322 }
11323 case TID_BITFIELD:
11324 sprintf(buf, "0x%X", *(((DWORD *) data) + idx));
11325 return buf;
11326 case TID_STRING:
11327 case TID_LINK:
11328 return (((char *) data) + data_size * idx);
11329 default:
11330 return "<unknown>";
11331 }
11332 }
11333}
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 11336 of file odb.cxx.

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

◆ db_unlock_database() [1/2]

void db_unlock_database ( DATABASE pdb,
const char *  caller 
)
static

Definition at line 2670 of file odb.cxx.

2671{
2672#ifdef CHECK_LOCK_COUNT
2673 {
2674 std::string str = msprintf("db_unlock_database, lock_cnt=%d", _database[hDB - 1].lock_cnt);
2675 ss_stack_history_entry(str.c_str());
2676 }
2677#endif
2678
2679 /* protect this function against recursive call from signal handlers */
2680 if (pdb->inside_lock_unlock) {
2681 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");
2682 abort();
2683 }
2684
2685 pdb->inside_lock_unlock = 1;
2686
2687 //static int x = 0;
2688 //x++;
2689 //if (x > 5000) {
2690 // printf("inside db_unlock_database(), press Ctrl-C now!\n");
2691 // sleep(5);
2692 //}
2693
2694 if (pdb->lock_cnt == 1) {
2696
2697 if (pdb->protect && pdb->database_header) {
2698 int status;
2699 assert(pdb->protect_read);
2700 assert(pdb->database_header);
2701 pdb->database_header = NULL;
2702 status = ss_shm_protect(pdb->shm_handle, pdb->shm_adr, pdb->shm_size);
2703 if (status != SS_SUCCESS) {
2704 cm_msg(MERROR, "db_unlock_database", "cannot unlock ODB, ss_shm_protect() failed with status %d, aborting...", status);
2706 abort();
2707 }
2708 pdb->protect_read = FALSE;
2709 pdb->protect_write = FALSE;
2710 }
2711 }
2712
2713 assert(pdb->lock_cnt > 0);
2714 pdb->lock_cnt--;
2715
2716 pdb->inside_lock_unlock = 0;
2717
2718 /* release mutex for multi-thread applications */
2719 ss_mutex_release(pdb->mutex);
2720}
INT ss_mutex_release(MUTEX_T *mutex)
Definition system.cxx:3229
Here is the call graph for this function:

◆ db_unlock_database() [2/2]

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 2648 of file odb.cxx.

2649{
2650#ifdef LOCAL_ROUTINES
2651
2652 if (hDB > _database_entries || hDB <= 0) {
2653 cm_msg(MERROR, "db_unlock_database", "invalid database handle %d", hDB);
2654 return DB_INVALID_HANDLE;
2655 }
2656
2657 DATABASE* pdb = &_database[hDB - 1];
2658
2659 db_unlock_database(pdb, "db_unlock_database");
2660
2661 return DB_SUCCESS;
2662
2663#else
2664 return DB_SUCCESS;
2665#endif
2666}
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 13920 of file odb.cxx.

13921{
13922#ifdef LOCAL_ROUTINES
13923 {
13924 INT i;
13925
13926 for (i = 0; i < _watch_list_entries; i++)
13927 if (_watch_list[i].handle == hKey && _watch_list[i].hDB == hDB)
13928 break;
13929
13930 if (i == _watch_list_entries)
13931 return DB_INVALID_HANDLE;
13932
13933 /* remove record entry from database structure */
13935
13936 memset(&_watch_list[i], 0, sizeof(WATCH_LIST));
13937 }
13938#endif /* LOCAL_ROUTINES */
13939
13940 return DB_SUCCESS;
13941}
static WATCH_LIST * _watch_list
Definition odb.cxx:61
static INT _watch_list_entries
Definition odb.cxx:62
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 13950 of file odb.cxx.

13951{
13952 for (int i = _watch_list_entries-1; i >= 0 ; i--) {
13953 if ((_watch_list[i].hDB == 0) && (_watch_list[i].handle == 0)) {
13954 // empty or deleted watch list entry
13955 continue;
13956 }
13958 }
13959
13960 return DB_SUCCESS;
13961}
INT db_unwatch(HNDLE hDB, HNDLE hKey)
Definition odb.cxx:13920
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 2776 of file odb.cxx.

2777{
2778 bool found = false;
2779 int pid = ss_getpid();
2780 for (int i = 0; i < _database_entries; i++) {
2781 if (_database[i].attached) {
2782 db_lock_database(i + 1);
2783 db_allow_write_locked(&_database[i], "db_update_last_activity");
2784 assert(_database[i].database_header);
2785 /* update the last_activity entry to show that we are alive */
2786 for (int j=0; j<_database[i].database_header->max_client_index; j++) {
2788 //printf("client %d pid %d vs our pid %d\n", j, pdbclient->pid, pid);
2789 if (pdbclient->pid == pid) {
2790 pdbclient->last_activity = millitime;
2791 found = true;
2792 }
2793 }
2794 db_unlock_database(i + 1);
2795 }
2796 }
2797
2798 if (!found) {
2799 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...");
2800 abort();
2801 }
2802
2803 return DB_SUCCESS;
2804}
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 1552 of file odb.cxx.

1553{
1554 int found = 0;
1555 int count = 0;
1556 int status;
1557 int k;
1559
1560 KEY* pkey = (KEY*)xpkey; // drop "const": we already have "allow_write"
1561
1562 HNDLE hKey = db_pkey_to_hkey(uorp->pheader, pkey);
1563
1564 for (k=0; k<uorp->num_keys; k++)
1565 if (uorp->hkeys[k] == hKey) {
1566 found = 1;
1567 count = uorp->counts[k];
1568 break;
1569 }
1570
1571 if (pkey->notify_count == 0 && !found)
1572 return DB_SUCCESS; // no open record here
1573
1574 std::string path = db_get_path_pkey(uorp->pheader, pkey);
1575 if (path == "") {
1576 db_msg(msg, MINFO, "db_update_open_record", "Invalid hKey %d", hKey);
1577 return DB_SUCCESS;
1578 }
1579
1580 //if (!db_validate_hkey(uorp->pheader, hKey)) {
1581 // cm_msg(MINFO, "db_update_open_record", "Invalid hKey %d", hKey);
1582 // return DB_SUCCESS;
1583 //}
1584 //
1585 //KEY* pkey = (KEY *) ((char *) uorp->pheader + hKey);
1586
1587 //printf("path [%s], type %d, notify_count %d\n", path, pkey->type, pkey->notify_count);
1588
1589 // extra check: are we looking at the same key?
1590 //assert(xkey->notify_count == pkey->notify_count);
1591
1592#if 0
1593 printf("%s, notify_count %d, found %d, our count %d\n", path, pkey->notify_count, found, count);
1594#endif
1595
1596 if (pkey->notify_count==0 && found) {
1597 db_msg(msg, MINFO, "db_update_open_record", "Added missing open record flag to \"%s\"", path.c_str());
1598 pkey->notify_count = count;
1599 uorp->num_modified++;
1600 return DB_SUCCESS;
1601 }
1602
1603 if (pkey->notify_count!=0 && !found) {
1604 db_msg(msg, MINFO, "db_update_open_record", "Removed open record flag from \"%s\"", path.c_str());
1605 pkey->notify_count = 0;
1606 uorp->num_modified++;
1607
1608 if (pkey->access_mode | MODE_EXCLUSIVE) {
1609 status = db_set_mode_wlocked(uorp->pheader, pkey, (WORD) (pkey->access_mode & ~MODE_EXCLUSIVE), 1, msg);
1610 if (status != DB_SUCCESS) {
1611 db_msg(msg, MERROR, "db_update_open_record", "Cannot remove exclusive access mode from \"%s\", db_set_mode() status %d", path.c_str(), status);
1612 return DB_SUCCESS;
1613 }
1614 db_msg(msg, MINFO, "db_update_open_record", "Removed exclusive access mode from \"%s\"", path.c_str());
1615 }
1616 return DB_SUCCESS;
1617 }
1618
1619 if (pkey->notify_count != uorp->counts[k]) {
1620 db_msg(msg, MINFO, "db_update_open_record", "Updated notify_count of \"%s\" from %d to %d", path.c_str(), pkey->notify_count, count);
1621 pkey->notify_count = count;
1622 uorp->num_modified++;
1623 return DB_SUCCESS;
1624 }
1625
1626 return DB_SUCCESS;
1627}
DATABASE_HEADER * pheader
Definition odb.cxx:1543
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 13584 of file odb.cxx.

13585{
13586 INT i, size, status;
13587
13589
13590 /* check all record entries for matching key */
13591 for (i = 0; i < _record_list_entries; i++)
13592 if (_record_list[i].handle == hKeyRoot) {
13594
13595 /* get updated data if record not opened in write mode */
13596 if ((_record_list[i].access_mode & MODE_WRITE) == 0) {
13597 size = _record_list[i].buf_size;
13598 if (_record_list[i].data != NULL) {
13599 status = db_get_record(hDB, hKeyRoot, _record_list[i].data, &size, 0); // db_open_record() update
13600 //printf("db_open_record update status %d, size %d %d\n", status, _record_list[i].buf_size, size);
13601 }
13602
13603 /* call dispatcher if requested */
13604 if (_record_list[i].dispatcher)
13606 }
13607 }
13608
13609 /* check all watch entries for matching key */
13610 for (i = 0; i < _watch_list_entries; i++)
13611 if (_watch_list[i].handle == hKeyRoot) {
13613
13614 /* call dispatcher if requested */
13615 if (_watch_list[i].dispatcher)
13617 }
13618
13619 return status;
13620}
void(* dispatcher)(INT, INT, INT, void *info)
Definition msystem.h:489
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 13631 of file odb.cxx.

13632{
13633 char buffer[32];
13634
13635 int convert_flags = rpc_get_convert_flags();
13636
13637 NET_COMMAND* nc = (NET_COMMAND *) buffer;
13638
13640 nc->header.param_size = 4 * sizeof(INT);
13641 *((INT *) nc->param) = hDB;
13642 *((INT *) nc->param + 1) = hKeyRoot;
13643 *((INT *) nc->param + 2) = hKey;
13644 *((INT *) nc->param + 3) = index;
13645
13646 if (convert_flags) {
13649 rpc_convert_single(&nc->param[0], TID_UINT32, RPC_OUTGOING, convert_flags);
13650 rpc_convert_single(&nc->param[4], TID_UINT32, RPC_OUTGOING, convert_flags);
13651 rpc_convert_single(&nc->param[8], TID_UINT32, RPC_OUTGOING, convert_flags);
13652 rpc_convert_single(&nc->param[12], TID_UINT32, RPC_OUTGOING, convert_flags);
13653 }
13654
13655 /* send the update notification to the client */
13656 send_tcp(client_socket, buffer, sizeof(NET_COMMAND_HEADER) + 4 * sizeof(INT), 0);
13657
13658 return DB_SUCCESS;
13659}
#define MSG_ODB
Definition msystem.h:303
INT send_tcp(int sock, char *buffer, DWORD buffer_size, INT flags)
Definition system.cxx:5357
NET_COMMAND_HEADER header
Definition msystem.h:293
char param[32]
Definition msystem.h:294
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 1692 of file odb.cxx.

1693{
1694 int total_size_key = 0;
1695 int total_size_data = 0;
1696 double ratio;
1697 FREE_DESCRIP *pfree;
1698 bool flag = true;
1699
1700 /* validate size of data structures (miscompiled, 32/64 bit mismatch, etc */
1701
1703
1704 /* validate the key free list */
1705
1706 if (!db_validate_key_offset(pheader, pheader->first_free_key)) {
1707 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));
1708 return false;
1709 }
1710
1711 pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_key);
1712
1713 while ((POINTER_T) pfree != (POINTER_T) pheader) {
1714
1715 if (pfree->next_free != 0 && !db_validate_key_offset(pheader, pfree->next_free)) {
1716 db_msg(msg, MERROR, "db_validate_db", "Warning: database corruption, invalid key area next_free 0x%08X", pfree->next_free - (int)sizeof(DATABASE_HEADER));
1717 flag = false;
1718 break;
1719 }
1720
1721 total_size_key += pfree->size;
1722 FREE_DESCRIP *nextpfree = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
1723
1724 if (pfree->next_free != 0 && nextpfree == pfree) {
1725 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));
1726 pfree->next_free = 0;
1727 flag = false;
1728 break;
1729 //return false;
1730 }
1731
1732 pfree = nextpfree;
1733 }
1734
1735 ratio = ((double) (pheader->key_size - total_size_key)) / ((double) pheader->key_size);
1736 if (ratio > 0.9)
1737 db_msg(msg, MERROR, "db_validate_db", "Warning: database key area is %.0f%% full", ratio * 100.0);
1738
1739 if (total_size_key > pheader->key_size) {
1740 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);
1741 flag = false;
1742 }
1743
1744 /* validate the data free list */
1745
1746 if (!db_validate_data_offset(pheader, pheader->first_free_data)) {
1747 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));
1748 return false;
1749 }
1750
1751 //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);
1752
1753 pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_data);
1754
1755 while ((POINTER_T) pfree != (POINTER_T) pheader) {
1756
1757 if (pfree->next_free != 0 && !db_validate_data_offset(pheader, pfree->next_free)) {
1758 db_msg(msg, MERROR, "db_validate_db", "Warning: database corruption, invalid data area next_free 0x%08X", pfree->next_free - (int)sizeof(DATABASE_HEADER));
1759 flag = false;
1760 break;
1761 //return false;
1762 }
1763
1764 total_size_data += pfree->size;
1765 FREE_DESCRIP *nextpfree = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
1766
1767 if (pfree->next_free != 0 && nextpfree == pfree) {
1768 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));
1769 pfree->next_free = 0;
1770 flag = false;
1771 break;
1772 //return false;
1773 }
1774
1775 pfree = nextpfree;
1776 }
1777
1778 ratio = ((double) (pheader->data_size - total_size_data)) / ((double) pheader->data_size);
1779 if (ratio > 0.9)
1780 db_msg(msg, MERROR, "db_validate_db", "Warning: database data area is %.0f%% full", ratio * 100.0);
1781
1782 if (total_size_data > pheader->data_size) {
1783 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);
1784 flag = false;
1785 //return false;
1786 }
1787
1788 /* validate the tree of keys, starting from the root key */
1789
1790 if (!db_validate_key_offset(pheader, pheader->root_key)) {
1791 db_msg(msg, MERROR, "db_validate_db", "Error: database corruption, pheader->root_key 0x%08X is invalid", pheader->root_key - (int)sizeof(DATABASE_HEADER));
1792 return false;
1793 }
1794
1795 flag &= db_validate_and_repair_key_wlocked(pheader, 1, "", 0, pheader->root_key, (KEY *) ((char *) pheader + pheader->root_key), msg);
1796
1797 if (!flag) {
1798 db_msg(msg, MERROR, "db_validate_db", "Error: ODB corruption detected, see previous messages");
1799 }
1800
1801 return flag;
1802}
static void db_validate_sizes()
Definition odb.cxx:1444
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 1173 of file odb.cxx.

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

936{
937 if (offset != 0 && offset < (int) sizeof(DATABASE_HEADER))
938 return false;
939
940 if (offset > (int) sizeof(DATABASE_HEADER) + pheader->key_size + pheader->data_size)
941 return false;
942
943 return true;
944}
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 946 of file odb.cxx.

947{
948 if (hKey == 0) {
949 cm_msg(MERROR, "db_validate_hkey", "Error: invalid zero hkey %d", hKey);
950 return false;
951 }
952 if (!db_validate_key_offset(pheader, hKey)) {
953 cm_msg(MERROR, "db_validate_hkey", "Error: invalid hkey %d", hKey);
954 return false;
955 }
956 return true;
957}
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 922 of file odb.cxx.

924{
925 if (offset != 0 && offset < (int) sizeof(DATABASE_HEADER))
926 return false;
927
928 if (offset > (int) sizeof(DATABASE_HEADER) + pheader->key_size)
929 return false;
930
931 return true;
932}
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 862 of file odb.cxx.

863{
864 //printf("db_validate_name [%s] length %d, maybe_path %d from %s\n", name, (int)strlen(name), maybe_path, caller_name);
865
866 if (name == NULL) {
867 db_msg(msg, MERROR, "db_validate_name", "Invalid name passed to %s: should not be NULL", caller_name);
868 return DB_INVALID_NAME;
869 }
870
871 size_t len = strlen(name);
872
873 if (len < 1) {
874 db_msg(msg, MERROR, "db_validate_name", "Invalid name passed to %s: should not be an empty string", caller_name);
875 return DB_INVALID_NAME;
876 }
877
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 (name[0] == ' ') {
884 db_msg(msg, MERROR, "db_validate_name", "Invalid name \"%s\" passed to %s: should not start with a space", name, caller_name);
885 return DB_INVALID_NAME;
886 }
887
888 if (name[len-1] == ' ') {
889 db_msg(msg, MERROR, "db_validate_name", "Invalid name \"%s\" passed to %s: should not end with a space", name, caller_name);
890 return DB_INVALID_NAME;
891 }
892
893 if (strchr(name, ']')) {
894 db_msg(msg, MERROR, "db_validate_name", "Invalid name \"%s\" passed to %s: should not contain \"[\"", name, caller_name);
895 return DB_INVALID_NAME;
896 }
897
898 if (!is_utf8(name)) {
899 db_msg(msg, MERROR, "db_validate_name", "Invalid name \"%s\" passed to %s: invalid unicode UTF-8 encoding", name, caller_name);
900 return DB_INVALID_NAME;
901 }
902
903 if (!maybe_path) {
904 if (strchr(name, '/')) {
905 db_msg(msg, MERROR, "db_validate_name", "Invalid name \"%s\" passed to %s: should not contain \"/\"", name, caller_name);
906 return DB_INVALID_NAME;
907 }
908
909 if (strlen(name) >= NAME_LENGTH) {
910 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);
911 return DB_INVALID_NAME;
912 }
913 }
914
915 //if (strcmp(name, "test")==0)
916 //return DB_INVALID_NAME;
917
918 return DB_SUCCESS;
919}
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 1629 of file odb.cxx.

1630{
1631 int status = DB_SUCCESS;
1633 int i, j, k;
1634
1636 uor.num_keys = 0;
1637 uor.hkeys = (HNDLE*)calloc(uor.max_keys, sizeof(HNDLE));
1638 uor.counts = (int*)calloc(uor.max_keys, sizeof(int));
1639 uor.modes = (int*)calloc(uor.max_keys, sizeof(int));
1640 uor.num_modified = 0;
1641
1642 assert(uor.hkeys != NULL);
1643 assert(uor.counts != NULL);
1644 assert(uor.modes != NULL);
1645
1646 uor.pheader = pheader;
1647
1648 for (i = 0; i < pheader->max_client_index; i++) {
1649 DATABASE_CLIENT* pclient = &pheader->client[i];
1650 for (j = 0; j < pclient->max_index; j++)
1651 if (pclient->open_record[j].handle) {
1652 int found = 0;
1653 for (k=0; k<uor.num_keys; k++) {
1654 if (uor.hkeys[k] == pclient->open_record[j].handle) {
1655 uor.counts[k]++;
1656 found = 1;
1657 break;
1658 }
1659 }
1660 if (!found) {
1661 uor.hkeys[uor.num_keys] = pclient->open_record[j].handle;
1662 uor.counts[uor.num_keys] = 1;
1663 uor.modes[uor.num_keys] = pclient->open_record[j].access_mode;
1664 uor.num_keys++;
1665 }
1666 }
1667 }
1668
1669#if 0
1670 for (i=0; i<uor.num_keys; i++)
1671 printf("index %d, handle %d, count %d, access mode %d\n", i, uor.hkeys[i], uor.counts[i], uor.modes[i]);
1672#endif
1673
1674 const KEY* proot = db_get_pkey(pheader, 0, &status, "db_validate_open_record", msg);
1675
1676 if (proot) {
1677 db_scan_tree_locked(pheader, proot, 0, db_update_open_record_wlocked, &uor, msg);
1678 }
1679
1680 if (uor.num_modified) {
1681 db_msg(msg, MINFO, "db_validate_open_records", "Corrected %d ODB entries", uor.num_modified);
1682 }
1683
1684 free(uor.hkeys);
1685 free(uor.counts);
1686 free(uor.modes);
1687
1688 return status;
1689}
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:1552
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 1444 of file odb.cxx.

1445{
1446 /* validate size of data structures (miscompiled, 32/64 bit mismatch, etc */
1447
1448 if (0) {
1449#define S(x) printf("assert(sizeof(%-20s) == %6d);\n", #x, (int)sizeof(x))
1450 // basic data types
1451 S(char *);
1452 S(char);
1453 S(int);
1454 S(long int);
1455 S(float);
1456 S(double);
1457 S(BOOL);
1458 S(WORD);
1459 S(DWORD);
1460 S(INT);
1461 S(POINTER_T);
1463 // data buffers
1467 // history files
1468 S(HIST_RECORD);
1469 S(DEF_RECORD);
1470 S(INDEX_RECORD);
1471 S(TAG);
1472 // ODB shared memory structures
1473 S(KEY);
1474 S(KEYLIST);
1475 S(OPEN_RECORD);
1478 // misc structures
1479 S(EVENT_HEADER);
1480 S(RUNINFO);
1483 S(BANK_HEADER);
1484 S(BANK);
1485 S(BANK32);
1487 S(PROGRAM_INFO);
1488 S(ALARM_CLASS);
1489 S(ALARM);
1490 //S(CHN_SETTINGS);
1491 //S(CHN_STATISTICS);
1492#undef S
1493 }
1494
1495#if 0
1497 printf("EQUIPMENT_INFO offset of event_id: %d\n", (int)((char*)&eq.event_id - (char*)&eq));
1498 printf("EQUIPMENT_INFO offset of eq_type: %d\n", (int)((char*)&eq.eq_type - (char*)&eq));
1499 printf("EQUIPMENT_INFO offset of event_limit: %d\n", (int)((char*)&eq.event_limit - (char*)&eq));
1500 printf("EQUIPMENT_INFO offset of num_subevents: %d\n", (int)((char*)&eq.num_subevents - (char*)&eq));
1501 printf("EQUIPMENT_INFO offset of status: %d\n", (int)((char*)&eq.status - (char*)&eq));
1502 printf("EQUIPMENT_INFO offset of hidden: %d\n", (int)((char*)&eq.hidden - (char*)&eq));
1503#endif
1504
1505 assert(sizeof(UINT8) == 1);
1506 assert(sizeof(INT8) == 1);
1507 assert(sizeof(UINT16) == 2);
1508 assert(sizeof(INT16) == 2);
1509 assert(sizeof(UINT32) == 4);
1510 assert(sizeof(INT32) == 4);
1511 assert(sizeof(UINT64) == 8);
1512 assert(sizeof(INT64) == 8);
1513
1514#ifdef OS_LINUX
1515 assert(sizeof(EVENT_REQUEST) == 16); // ODB v3
1516 assert(sizeof(BUFFER_CLIENT) == 256);
1517 assert(sizeof(BUFFER_HEADER) == 16444);
1518 assert(sizeof(HIST_RECORD) == 20);
1519 assert(sizeof(DEF_RECORD) == 40);
1520 assert(sizeof(INDEX_RECORD) == 12);
1521 assert(sizeof(TAG) == 40);
1522 assert(sizeof(KEY) == 68);
1523 assert(sizeof(KEYLIST) == 12);
1524 assert(sizeof(OPEN_RECORD) == 8);
1525 assert(sizeof(DATABASE_CLIENT) == 2112);
1526 assert(sizeof(DATABASE_HEADER) == 135232);
1527 assert(sizeof(EVENT_HEADER) == 16);
1528 //assert(sizeof(EQUIPMENT_INFO) == 696); has been moved to dynamic checking inside mhttpd.c
1529 assert(sizeof(EQUIPMENT_STATS) == 24);
1530 assert(sizeof(BANK_HEADER) == 8);
1531 assert(sizeof(BANK) == 8);
1532 assert(sizeof(BANK32) == 12);
1533 assert(sizeof(ANA_OUTPUT_INFO) == 792);
1534 assert(sizeof(PROGRAM_INFO) == 316);
1535 assert(sizeof(ALARM) == 460);
1536 assert(sizeof(ALARM_CLASS) == 352);
1537 //assert(sizeof(CHN_SETTINGS) == 648); // ODB v3
1538 //assert(sizeof(CHN_STATISTICS) == 56); // ODB v3
1539#endif
1540}
std::vector< FMT_ID > eq
Definition mdump.cxx:55
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:1214
Definition midas.h:1233
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 4 parameters: the database handle, the key handle of the entry that changed (could be a child if you're watching a directory), the index that changed (if it was part of an array), a user-specified 'info' parameter.

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, INT idx, void* info
Returns
DB_SUCCESS, DB_INVALID_HANDLE, DB_NO_MEMORY, DB_NO_ACCESS, DB_STRUCT_SIZE_MISMATCH

Definition at line 13845 of file odb.cxx.

13846{
13847 INT idx, status;
13848 KEY key;
13849
13850 /* check for valid key */
13851 assert(hKey);
13852
13853 /* allocate new space for the local record list */
13854 if (_watch_list_entries == 0) {
13855 _watch_list = (WATCH_LIST *) malloc(sizeof(WATCH_LIST));
13856 assert(_watch_list != NULL);
13857 memset(_watch_list, 0, sizeof(WATCH_LIST));
13858 if (_watch_list == NULL) {
13859 cm_msg(MERROR, "db_watch", "not enough memory");
13860 return DB_NO_MEMORY;
13861 }
13862
13864 idx = 0;
13865 } else {
13866 /* check for a deleted entry */
13867 for (idx = 0; idx < _watch_list_entries; idx++)
13868 if (!_watch_list[idx].handle)
13869 break;
13870
13871 /* if not found, create new one */
13872 if (idx == _watch_list_entries) {
13873 _watch_list = (WATCH_LIST *) realloc(_watch_list, sizeof(WATCH_LIST) * (_watch_list_entries + 1));
13874 if (_watch_list == NULL) {
13875 cm_msg(MERROR, "db_watch", "not enough memory");
13876 return DB_NO_MEMORY;
13877 }
13878
13879 memset(&_watch_list[_watch_list_entries], 0, sizeof(WATCH_LIST));
13880
13882 }
13883 }
13884
13885 /* check key */
13887 if (status != DB_SUCCESS) {
13889 std::string path = db_get_path(hDB, hKey);
13890 cm_msg(MERROR, "db_watch", "cannot get key \"%s\"", path.c_str());
13891 return DB_NO_MEMORY;
13892 }
13893
13894 /* check for read access */
13895 if (!(key.access_mode & MODE_READ)) {
13897 std::string path = db_get_path(hDB, hKey);
13898 cm_msg(MERROR, "db_watch", "cannot get key \"%s\"", path.c_str());
13899 return DB_NO_ACCESS;
13900 }
13901
13902 /* initialize record list */
13903 _watch_list[idx].handle = hKey;
13904 _watch_list[idx].hDB = hDB;
13905 _watch_list[idx].dispatcher = dispatcher;
13906 _watch_list[idx].info = info;
13907
13908 /* add record entry in database structure */
13910}
#define MODE_WATCH
Definition midas.h:375
HNDLE handle
Definition msystem.h:487
HNDLE hDB
Definition msystem.h:488
void * info
Definition msystem.h:490
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 3306 of file odb.cxx.

3307{
3308 int len_str = strlen(str);
3309 int len_suffix = strlen(suffix);
3310
3311 // suffix is longer than the string
3312 if (len_suffix > len_str)
3313 return FALSE;
3314
3315 return equal_ustring(str + len_str - len_suffix, suffix);
3316}
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 3285 of file odb.cxx.

3286{
3287 if (str1 == NULL && str2 != NULL)
3288 return FALSE;
3289 if (str1 != NULL && str2 == NULL)
3290 return FALSE;
3291 if (str1 == NULL && str2 == NULL)
3292 return TRUE;
3293 if (strlen(str1) != strlen(str2))
3294 return FALSE;
3295
3296 while (*str1)
3297 if (toupper(*str1++) != toupper(*str2++))
3298 return FALSE;
3299
3300 if (*str2)
3301 return FALSE;
3302
3303 return TRUE;
3304}

◆ extract_key()

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

Definition at line 3271 of file odb.cxx.

3272{
3273 int i = 0;
3274
3275 if (*key_list == '/')
3276 key_list++;
3277
3278 while (*key_list && *key_list != '/' && ++i < key_name_length)
3279 *key_name++ = *key_list++;
3280 *key_name = 0;
3281
3282 return key_list;
3283}
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 516 of file odb.cxx.

517{
518 if (size == 0)
519 return DB_SUCCESS;
520
521 assert(address != pheader);
522
523 /* quadword alignment for alpha CPU */
524 size = ALIGN8(size);
525
526 /* smallest allocation size is 8 bytes to make sure we can always create a new FREE_DESCRIP in free_data() */
527 assert(size >= (int)sizeof(FREE_DESCRIP));
528
529 FREE_DESCRIP *pprev = NULL;
530 FREE_DESCRIP *pfree = (FREE_DESCRIP *) address;
531 int pfree_offset = (POINTER_T) address - (POINTER_T) pheader;
532
533 /* clear current block */
534 memset(address, 0, size);
535
536 if (pheader->first_free_data == 0) {
537 /* if free list is empty, create the first free block, adjust pheader */
538 pfree->size = size;
539 pfree->next_free = 0;
540 pheader->first_free_data = pfree_offset;
541 /* nothing else to do */
542 return DB_SUCCESS;
543 } else if ((POINTER_T) address - (POINTER_T) pheader < pheader->first_free_data) {
544 /* if data comes before first free block, create new free block, adjust pheader */
545 pfree->size = size;
546 pfree->next_free = pheader->first_free_data;
547 pheader->first_free_data = pfree_offset;
548 /* maybe merge next free block into the new free block */
549 //printf("free_data: created new first free block, maybe merge with old first free block\n");
550 } else {
551 /* find last free block before current block */
552 pprev = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_data);
553
554 while (pprev->next_free < pfree_offset) {
555 if (pprev->next_free == 0) {
556 /* add new free block at the end of the chain of free blocks */
557 //printf("free_data: adding new free block at the very end\n");
558 break;
559 }
560 if (!validate_free_data(pheader, pprev->next_free)) {
561 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);
562 return DB_CORRUPTED;
563 }
564
565 pprev = (FREE_DESCRIP *) ((char *) pheader + pprev->next_free);
566 }
567
568 pfree->size = size;
569 pfree->next_free = pprev->next_free;
570
571 pprev->next_free = pfree_offset;
572 }
573
574 /* try to melt adjacent free blocks after current block */
575 FREE_DESCRIP *pnext = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
576 if ((POINTER_T) pnext == (POINTER_T) pfree + pfree->size) {
577 //printf("free_data: merging first and second free block\n");
578 pfree->size += pnext->size;
579 pfree->next_free = pnext->next_free;
580
581 memset(pnext, 0, pnext->size);
582 }
583
584 /* try to melt adjacent free blocks before current block */
585 if (pprev && pprev->next_free == (POINTER_T) pprev - (POINTER_T) pheader + pprev->size) {
586 //printf("free_data: merging pprev and pfree\n");
587 pprev->size += pfree->size;
588 pprev->next_free = pfree->next_free;
589
590 memset(pfree, 0, pfree->size);
591 }
592
593 return DB_SUCCESS;
594}
static int validate_free_data(DATABASE_HEADER *pheader, int free_data)
Definition odb.cxx:404
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 345 of file odb.cxx.

346{
347 FREE_DESCRIP *pfree, *pprev, *pnext;
348
349 if (size == 0)
350 return;
351
352 assert(address != pheader);
353
354 /* quadword alignment for alpha CPU */
355 size = ALIGN8(size);
356
357 pfree = (FREE_DESCRIP *) address;
358 pprev = NULL;
359
360 /* clear current block */
361 memset(address, 0, size);
362
363 /* if key comes before first free block, adjust pheader */
364 if ((POINTER_T) address - (POINTER_T) pheader < pheader->first_free_key) {
365 pfree->size = size;
366 pfree->next_free = pheader->first_free_key;
367 pheader->first_free_key = (POINTER_T) address - (POINTER_T) pheader;
368 } else {
369 /* find last free block before current block */
370 pprev = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_key);
371
372 while (pprev->next_free < (POINTER_T) address - (POINTER_T) pheader) {
373 if (pprev->next_free <= 0) {
374 cm_msg(MERROR, "free_key", "database is corrupted: pprev=%p, pprev->next_free=%d", pprev, pprev->next_free);
375 return;
376 }
377 pprev = (FREE_DESCRIP *) ((char *) pheader + pprev->next_free);
378 }
379
380 pfree->size = size;
381 pfree->next_free = pprev->next_free;
382
383 pprev->next_free = (POINTER_T) pfree - (POINTER_T) pheader;
384 }
385
386 /* try to melt adjacent free blocks after current block */
387 pnext = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
388 if ((POINTER_T) pnext == (POINTER_T) pfree + pfree->size) {
389 pfree->size += pnext->size;
390 pfree->next_free = pnext->next_free;
391
392 memset(pnext, 0, pnext->size);
393 }
394
395 /* try to melt adjacent free blocks before current block */
396 if (pprev && pprev->next_free == (POINTER_T) pprev - (POINTER_T) pheader + pprev->size) {
397 pprev->size += pfree->size;
398 pprev->next_free = pfree->next_free;
399
400 memset(pfree, 0, pfree->size);
401 }
402}
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 851 of file odb.cxx.

852{
853 if (!string)
854 return false;
855
856 return ss_is_valid_utf8(string);
857}
bool ss_is_valid_utf8(const char *string)
Definition system.cxx:8146
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 9650 of file odb.cxx.

9651{
9652 // sprintf "%.2e" can result in strings like "1,23e6" if
9653 // the user's locale has a comma for the decimal spearator.
9654 // However the JSON RFC requires a dot for the decimal.
9655 // This approach of "sprintf-then-replace" is much safer than
9656 // changing the user's locale, and much faster than the C++
9657 // approach of using a stringstream that we "imbue" with a C locale.
9658 char* comma = strchr(str, ',');
9659
9660 if (comma != nullptr) {
9661 *comma = '.';
9662 }
9663}
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 9550 of file odb.cxx.

9551{
9552 int len, remain, xlevel;
9553
9554 len = strlen(s);
9555 remain = *buffer_size - *buffer_end;
9556 assert(remain >= 0);
9557
9558 xlevel = 2*level;
9559
9560 while (10 + xlevel + 3*len > remain) {
9561 // reallocate the buffer
9562 int new_buffer_size = 2*(*buffer_size);
9563 if (new_buffer_size < 4*1024)
9564 new_buffer_size = 4*1024;
9565 //printf("reallocate: len %d, size %d, remain %d, allocate %d\n", len, *buffer_size, remain, new_buffer_size);
9566 assert(new_buffer_size > *buffer_size);
9567 *buffer = (char *)realloc(*buffer, new_buffer_size);
9568 assert(*buffer);
9569 *buffer_size = new_buffer_size;
9570 remain = *buffer_size - *buffer_end;
9571 assert(remain >= 0);
9572 }
9573
9574 if (xlevel) {
9575 int i;
9576 for (i=0; i<xlevel; i++)
9577 (*buffer)[(*buffer_end)++] = ' ';
9578 }
9579
9580 if (!quoted) {
9581 memcpy(*buffer + *buffer_end, s, len);
9582 *buffer_end += len;
9583 (*buffer)[*buffer_end] = 0; // NUL-terminate the buffer
9584 return;
9585 }
9586
9587 char *bufptr = *buffer;
9588 int bufend = *buffer_end;
9589
9590 bufptr[bufend++] = '"';
9591
9592 while (*s) {
9593 switch (*s) {
9594 case '\"':
9595 bufptr[bufend++] = '\\';
9596 bufptr[bufend++] = '\"';
9597 s++;
9598 break;
9599 case '\\':
9600 bufptr[bufend++] = '\\';
9601 bufptr[bufend++] = '\\';
9602 s++;
9603 break;
9604#if 0
9605 case '/':
9606 bufptr[bufend++] = '\\';
9607 bufptr[bufend++] = '/';
9608 s++;
9609 break;
9610#endif
9611 case '\b':
9612 bufptr[bufend++] = '\\';
9613 bufptr[bufend++] = 'b';
9614 s++;
9615 break;
9616 case '\f':
9617 bufptr[bufend++] = '\\';
9618 bufptr[bufend++] = 'f';
9619 s++;
9620 break;
9621 case '\n':
9622 bufptr[bufend++] = '\\';
9623 bufptr[bufend++] = 'n';
9624 s++;
9625 break;
9626 case '\r':
9627 bufptr[bufend++] = '\\';
9628 bufptr[bufend++] = 'r';
9629 s++;
9630 break;
9631 case '\t':
9632 bufptr[bufend++] = '\\';
9633 bufptr[bufend++] = 't';
9634 s++;
9635 break;
9636 default:
9637 bufptr[bufend++] = *s++;
9638 }
9639 }
9640
9641 bufptr[bufend++] = '"';
9642 bufptr[bufend] = 0; // NUL-terminate the buffer
9643
9644 *buffer_end = bufend;
9645
9646 remain = *buffer_size - *buffer_end;
9647 assert(remain > 0);
9648}
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 10405 of file odb.cxx.

10406{
10407 int status;
10408 KEY key;
10409
10411 if (status != DB_SUCCESS)
10412 return status;
10413
10414 if (key.type == TID_KEY) {
10415
10416 json_write(buffer, buffer_size, buffer_end, 0, "{", 0);
10417
10418 status = json_write_bare_subdir(hDB, hKey, buffer, buffer_size, buffer_end, level+1, flags, timestamp);
10419 if (status != DB_SUCCESS)
10420 return status;
10421
10422 json_write(buffer, buffer_size, buffer_end, 0, "\n", 0);
10423 json_write(buffer, buffer_size, buffer_end, level, "}", 0);
10424
10425 } else if (must_be_subdir) {
10426 json_write(buffer, buffer_size, buffer_end, 0, "{", 0);
10427 status = json_write_bare_key(hDB, hKey, key, buffer, buffer_size, buffer_end, level+1, flags, timestamp, false);
10428 if (status != DB_SUCCESS)
10429 return status;
10430 json_write(buffer, buffer_size, buffer_end, 0, "\n", 0);
10431 json_write(buffer, buffer_size, buffer_end, level, "}", 0);
10432 } else {
10433 status = db_copy_json_array(hDB, hKey, buffer, buffer_size, buffer_end);
10434
10435 if (status != DB_SUCCESS)
10436 return status;
10437 }
10438
10439 return DB_SUCCESS;
10440}
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:10273
INT db_copy_json_array(HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end)
Definition odb.cxx:10173
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 10273 of file odb.cxx.

10274{
10275 int status;
10276 char link_buf[MAX_ODB_PATH]; // link_path points to link_buf
10277 char* link_path = NULL;
10278
10279 HNDLE hLinkTarget = hLink;
10280
10281 if (link.type == TID_LINK) {
10282 int size = sizeof(link_buf);
10283 status = db_get_link_data(hDB, hLink, link_buf, &size, TID_LINK);
10284 if (status != DB_SUCCESS)
10285 return status;
10286
10287 //printf("link size %d, len %d, data [%s]\n", size, (int)strlen(link_buf), link_buf);
10288
10289 if ((size > 0) && (strlen(link_buf) > 0)) {
10290 link_path = link_buf;
10291
10292 // resolve the link, unless it is a link to an array element
10293 if ((flags & JSFLAG_FOLLOW_LINKS) && strchr(link_path, '[') == NULL) {
10294 status = db_find_key(hDB, 0, link_path, &hLinkTarget);
10295 if (status != DB_SUCCESS) {
10296 // dangling link to nowhere
10297 hLinkTarget = hLink;
10298 }
10299 }
10300 }
10301 }
10302
10303 KEY link_target;
10304 status = db_get_key(hDB, hLinkTarget, &link_target);
10305 if (status != DB_SUCCESS)
10306 return status;
10307
10308 if (flags & JSFLAG_OMIT_OLD) {
10309 if (link_target.last_written) {
10310 if (link_target.last_written < timestamp) {
10311 // omit old data
10312 return DB_SUCCESS;
10313 }
10314 }
10315 }
10316
10317 if (need_comma) {
10318 json_write(buffer, buffer_size, buffer_end, 0, ",\n", 0);
10319 } else {
10320 json_write(buffer, buffer_size, buffer_end, 0, "\n", 0);
10321 }
10322
10323 char link_name[MAX_ODB_PATH];
10324
10325 mstrlcpy(link_name, link.name, sizeof(link_name));
10326
10327 if (flags & JSFLAG_LOWERCASE) {
10328 for (int i=0; (i<(int)sizeof(link.name)) && link.name[i]; i++)
10329 link_name[i] = tolower(link.name[i]);
10330 }
10331
10332 if ((flags & JSFLAG_LOWERCASE) && !(flags & JSFLAG_OMIT_NAMES)) {
10333 char buf[MAX_ODB_PATH];
10334 mstrlcpy(buf, link_name, sizeof(buf));
10335 mstrlcat(buf, "/name", sizeof(buf));
10336 json_write(buffer, buffer_size, buffer_end, level, buf, 1);
10337 json_write(buffer, buffer_size, buffer_end, 0, " : " , 0);
10338 json_write(buffer, buffer_size, buffer_end, 0, link.name, 1);
10339 json_write(buffer, buffer_size, buffer_end, 0, ",\n", 0);
10340 }
10341
10342 if (link.type != TID_KEY && (flags & JSFLAG_SAVE_KEYS)) {
10343 char buf[MAX_ODB_PATH];
10344 mstrlcpy(buf, link_name, sizeof(buf));
10345 mstrlcat(buf, "/key", sizeof(buf));
10346 json_write(buffer, buffer_size, buffer_end, level, buf, 1);
10347 json_write(buffer, buffer_size, buffer_end, 0, " : " , 0);
10348 json_write_key(hDB, hLink, &link_target, link_path, buffer, buffer_size, buffer_end);
10349 json_write(buffer, buffer_size, buffer_end, 0, ",\n", 0);
10350 } else if ((link_target.type != TID_KEY) && !(flags & JSFLAG_OMIT_LAST_WRITTEN)) {
10351 char buf[MAX_ODB_PATH];
10352 mstrlcpy(buf, link_name, sizeof(buf));
10353 mstrlcat(buf, "/last_written", sizeof(buf));
10354 json_write(buffer, buffer_size, buffer_end, level, buf, 1);
10355 json_write(buffer, buffer_size, buffer_end, 0, " : " , 0);
10356 sprintf(buf, "%d", link_target.last_written);
10357 json_write(buffer, buffer_size, buffer_end, 0, buf, 0);
10358 json_write(buffer, buffer_size, buffer_end, 0, ",\n", 0);
10359 }
10360
10361 json_write(buffer, buffer_size, buffer_end, level, link_name, 1);
10362 json_write(buffer, buffer_size, buffer_end, 0, " : " , 0);
10363
10364 if (link_target.type == TID_KEY && !(flags & JSFLAG_RECURSE)) {
10365 json_write(buffer, buffer_size, buffer_end, 0, "{ }" , 0);
10366 } else {
10367 status = json_write_anything(hDB, hLinkTarget, buffer, buffer_size, buffer_end, level, 0, flags, timestamp);
10368 if (status != DB_SUCCESS)
10369 return status;
10370 }
10371
10372 return DB_SUCCESS;
10373}
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:9782
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 10375 of file odb.cxx.

10376{
10377 if (level > MAX_ODB_PATH) {
10378 cm_msg(MERROR, "json_write_bare_subdir", "Max ODB subdirectory nesting level exceeded %d at \"%s\"", level, db_get_path(hDB, hKey).c_str());
10379 return DB_TRUNCATED;
10380 }
10381
10382 for (int i=0; ; i++) {
10383 int status;
10384
10385 HNDLE hLink;
10386 status = db_enum_link(hDB, hKey, i, &hLink);
10387 if (status != DB_SUCCESS && !hLink)
10388 break;
10389
10390 KEY link;
10391 status = db_get_link(hDB, hLink, &link);
10392 if (status != DB_SUCCESS)
10393 return status;
10394
10395 bool need_comma = (i!=0);
10396
10397 status = json_write_bare_key(hDB, hLink, link, buffer, buffer_size, buffer_end, level, flags, timestamp, need_comma);
10398 if (status != DB_SUCCESS)
10399 return status;
10400 }
10401
10402 return DB_SUCCESS;
10403}
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 9665 of file odb.cxx.

9666{
9667 char str[256];
9668 switch (key->type) {
9669 case TID_UINT8:
9670 sprintf(str, "%u", *(unsigned char*)p);
9671 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9672 break;
9673 case TID_INT8:
9674 sprintf(str, "%d", *(char*)p);
9675 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9676 break;
9677 case TID_CHAR:
9678 sprintf(str, "%c", *(char*)p);
9679 json_write(buffer, buffer_size, buffer_end, 0, str, 1);
9680 break;
9681 case TID_UINT16:
9682 sprintf(str, "\"0x%04x\"", *(WORD*)p);
9683 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9684 break;
9685 case TID_INT16:
9686 sprintf(str, "%d", *(short*)p);
9687 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9688 break;
9689 case TID_UINT32:
9690 sprintf(str, "\"0x%08x\"", *(DWORD*)p);
9691 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9692 break;
9693 case TID_INT32:
9694 sprintf(str, "%d", *(int*)p);
9695 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9696 break;
9697 case TID_UINT64:
9698 // encode as hex string
9699 sprintf(str, "\"0x%016llx\"", *(UINT64*)p);
9700 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9701 break;
9702 case TID_INT64:
9703 // encode as decimal string
9704 sprintf(str, "\"%lld\"", *(INT64*)p);
9705 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9706 break;
9707 case TID_BOOL:
9708 if (*(int*)p)
9709 json_write(buffer, buffer_size, buffer_end, 0, "true", 0);
9710 else
9711 json_write(buffer, buffer_size, buffer_end, 0, "false", 0);
9712 break;
9713 case TID_FLOAT: {
9714 float flt = (*(float*)p);
9715 if (isnan(flt))
9716 json_write(buffer, buffer_size, buffer_end, 0, "\"NaN\"", 0);
9717 else if (isinf(flt)) {
9718 if (flt > 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 (flt == 0)
9723 json_write(buffer, buffer_size, buffer_end, 0, "0", 0);
9724 else if (flt == (int)flt) {
9725 sprintf(str, "%.0f", flt);
9727 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9728 } else {
9729 sprintf(str, "%.7e", flt);
9731 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9732 }
9733 break;
9734 }
9735 case TID_DOUBLE: {
9736 double dbl = (*(double*)p);
9737 if (isnan(dbl))
9738 json_write(buffer, buffer_size, buffer_end, 0, "\"NaN\"", 0);
9739 else if (isinf(dbl)) {
9740 if (dbl > 0)
9741 json_write(buffer, buffer_size, buffer_end, 0, "\"Infinity\"", 0);
9742 else
9743 json_write(buffer, buffer_size, buffer_end, 0, "\"-Infinity\"", 0);
9744 } else if (dbl == 0)
9745 json_write(buffer, buffer_size, buffer_end, 0, "0", 0);
9746 else if (dbl == (int)dbl) {
9747 sprintf(str, "%.0f", dbl);
9749 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9750 } else {
9751 sprintf(str, "%.16e", dbl);
9753 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9754 }
9755 break;
9756 }
9757 case TID_BITFIELD:
9758 json_write(buffer, buffer_size, buffer_end, 0, "(TID_BITFIELD value)", 1);
9759 break;
9760 case TID_STRING:
9761 // data is already NUL terminated // p[key.item_size-1] = 0; // make sure string is NUL terminated!
9762 json_write(buffer, buffer_size, buffer_end, 0, p, 1);
9763 break;
9764 case TID_ARRAY:
9765 json_write(buffer, buffer_size, buffer_end, 0, "(TID_ARRAY value)", 1);
9766 break;
9767 case TID_STRUCT:
9768 json_write(buffer, buffer_size, buffer_end, 0, "(TID_STRUCT value)", 1);
9769 break;
9770 case TID_KEY:
9771 json_write(buffer, buffer_size, buffer_end, 0, "{ }", 0);
9772 break;
9773 case TID_LINK:
9774 // data is already NUL terminated // p[key.item_size-1] = 0; // make sure string is NUL terminated!
9775 json_write(buffer, buffer_size, buffer_end, 0, p, 1);
9776 break;
9777 default:
9778 json_write(buffer, buffer_size, buffer_end, 0, "(TID_UNKNOWN value)", 1);
9779 }
9780}
static void json_ensure_decimal_dot(char *str)
Definition odb.cxx:9650
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 9782 of file odb.cxx.

9783{
9784 char str[256]; // not used to store anything long, only numeric values like: "item_size: 100"
9785
9786 json_write(buffer, buffer_size, buffer_end, 0, "{ ", 0);
9787
9788 sprintf(str, "\"type\" : %d", key->type);
9789 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9790
9791 if (link_path) {
9792 json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9793 json_write(buffer, buffer_size, buffer_end, 0, "link", 1);
9794 json_write(buffer, buffer_size, buffer_end, 0, ": ", 0);
9795 json_write(buffer, buffer_size, buffer_end, 0, link_path, 1);
9796 }
9797
9798 if (key->num_values > 1) {
9799 json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9800
9801 sprintf(str, "\"num_values\" : %d", key->num_values);
9802 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9803 }
9804
9805 if (key->type == TID_STRING) {
9806 json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9807
9808 sprintf(str, "\"item_size\" : %d", key->item_size);
9809 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9810 }
9811
9812 if (key->notify_count > 0) {
9813 json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9814
9815 sprintf(str, "\"notify_count\" : %d", key->notify_count);
9816 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9817 }
9818
9819 json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9820
9821 sprintf(str, "\"access_mode\" : %d", key->access_mode);
9822 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9823
9824 json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9825
9826 sprintf(str, "\"last_written\" : %d", key->last_written);
9827 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9828
9829 json_write(buffer, buffer_size, buffer_end, 0, " ", 0);
9830
9831 json_write(buffer, buffer_size, buffer_end, 0, "}", 0);
9832}
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 428 of file odb.cxx.

429{
430 if (size == 0)
431 return NULL;
432
433 assert(size > 0);
434
435 /* quadword alignment for alpha CPU */
436 size = ALIGN8(size);
437
438 /* smallest allocation size is 8 bytes to make sure we can always create a new FREE_DESCRIP in free_data() */
439 assert(size >= (int)sizeof(FREE_DESCRIP));
440
441 if (!validate_free_data(pheader, pheader->first_free_data)) {
442 return NULL;
443 }
444
445 /* search for free block */
446 FREE_DESCRIP *pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_data);
447 FREE_DESCRIP *pprev = NULL;
448 FREE_DESCRIP *pfound = NULL;
449
450 while (1) {
451 //printf("malloc_data: pprev %p, pfree %p, next %d, size %d, want %d\n", pprev, pfree, pfree->next_free, pfree->size, size);
452
453 if (pfree->size >= size) {
454 // we will use this block
455 pfound = pfree;
456 break;
457 }
458
459 if (!pfree->next_free) {
460 // no more free blocks
461 return NULL;
462 }
463
464 if (!validate_free_data(pheader, pfree->next_free)) {
465 // next_free is invalid
466 //printf("malloc_data: pprev %p, pfree %p, next %d, size %d, next is invalid\n", pprev, pfree, pfree->next_free, pfree->size);
467 return NULL;
468 }
469 pprev = pfree;
470 pfree = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
471 }
472
473 //printf("malloc_data: pprev %p, pfound %p, size %d, want %d\n", pprev, pfound, pfound->size, size);
474
475 assert(pfound != NULL);
476 assert(size <= pfound->size);
477
478 /* if found block is first in list, correct pheader */
479 if (!pprev) {
480 if (size < pfree->size) {
481 /* free block is only used partially */
482 pheader->first_free_data += size;
483 pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_data);
484
485 pfree->size = pfound->size - size;
486 pfree->next_free = pfound->next_free;
487 } else {
488 /* free block is used totally */
489 pheader->first_free_data = pfree->next_free;
490 }
491 } else {
492 /* check if free block is used totally */
493 if (pfound->size - size < (int) sizeof(FREE_DESCRIP)) {
494 /* delete this free block from the free blocks chain */
495 pprev->next_free = pfound->next_free;
496 } else {
497 /* decrease free block */
498 pfree = (FREE_DESCRIP *) ((char *) pfound + size);
499
500 pfree->size = pfound->size - size;
501 pfree->next_free = pfound->next_free;
502
503 pprev->next_free = (POINTER_T) pfree - (POINTER_T) pheader;
504 }
505 }
506
507 assert((void*)pfound != (void*)pheader);
508
509 /* zero memeory */
510 memset(pfound, 0, size);
511
512 return pfound;
513}
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 226 of file odb.cxx.

227{
228 // Notes:
229 // we allocate objects:
230 // KEY aligned size 72
231 // KEYLIST aligned size 16
232 // they are not multiples of each other and we need to be
233 // careful to avoid 8-byte allocation holes.
234 // K.O.
235
236 if (size == 0)
237 return NULL;
238
239 assert(size == sizeof(KEY) || size == sizeof(KEYLIST));
240
241 /* quadword alignment for alpha CPU */
242 size = ALIGN8(size);
243
244 //printf("malloc_key(%d) from [%s]\n", size, caller);
245
246 if (!db_validate_key_offset(pheader, pheader->first_free_key)) {
247 return NULL;
248 }
249
250 /* search for free block */
251
252 bool have_good_block = false;
253 int pass = 1;
254 FREE_DESCRIP* pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_key);
255 FREE_DESCRIP* pprev = NULL;
256
257 while (1) {
258 //printf("pfree %p, size %3d, next_free %7d, pprev %p, want %3d, pass %d\n", pfree, pfree->size, pfree->next_free, pprev, size, pass);
259
260 if (pfree->size >= size) { // found free block
261 have_good_block = true;
262 if (pass == 1) {
263 // do not use a free block if remaining size is smaller than 16 (aligned size of KEYLIST)
264 // because it will become dead space we cannot use for anything. K.O.
265 int remaining = pfree->size - size;
266 if ((remaining == 0) || (remaining >= (int)ALIGN8(sizeof(KEYLIST))))
267 break;
268 } else {
269 // first pass could not find any free blocks we like,
270 // second pass will use whatever fits. K.O.
271 break;
272 }
273 }
274
275 if (pfree->next_free == 0) { // last block
276 //printf("pfree %p, size %3d, next_free %7d, pprev %p, want %3d, pass %d, out of free blocks, have_good_block %d\n", pfree, pfree->size, pfree->next_free, pprev, size, pass, have_good_block);
277 if (pass == 1 && have_good_block) {
278 // try again from scratch
279 pass = 2;
280 pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_key);
281 pprev = NULL;
282 continue;
283 }
284 return NULL;
285 }
286
287 if (!db_validate_key_offset(pheader, pfree->next_free)) {
288 return NULL;
289 }
290
291 pprev = pfree;
292 pfree = (FREE_DESCRIP *) ((char *) pheader + pfree->next_free);
293 }
294
295 //printf("found free block %p size %d, want %d\n", pfree, pfree->size, size);
296
297 assert(pfree->size >= size);
298
299 FREE_DESCRIP* pfound = pfree;
300
301 /* if found block is first in list, correct pheader */
302 if (pfree == (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_key)) {
303 if (size < pfree->size) {
304 /* free block is only used partially */
305 pheader->first_free_key += size;
306 pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_key);
307
308 pfree->size = pfound->size - size;
309 pfree->next_free = pfound->next_free;
310 } else {
311 /* free block is used totally */
312 pheader->first_free_key = pfree->next_free;
313 }
314 } else {
315 /* check if free block is used totally */
316 if (pfound->size - size < (int) sizeof(FREE_DESCRIP)) {
317 if (pfound->next_free == 0) {
318 // we are about to kill the very last free block
319 // let's not do it, free_key() cannot recover from this
320 // and we lose most of the free space. K.O.
321 //printf("found free block %p size %d, want %d, this will kill the last free block\n", pfree, pfree->size, size);
322 return NULL;
323 }
324 /* skip block totally */
325 pprev->next_free = pfound->next_free;
326 } else {
327 /* decrease free block */
328 pfree = (FREE_DESCRIP *) ((char *) pfound + size);
329
330 pfree->size = pfound->size - size;
331 pfree->next_free = pfound->next_free;
332
333 pprev->next_free = (POINTER_T) pfree - (POINTER_T) pheader;
334 }
335 }
336
337 assert((void*)pfound != (void*)pheader);
338
339 memset(pfound, 0, size);
340
341 return pfound;
342}
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 12690 of file odb.cxx.

12691{
12692 char full_name[MAX_ODB_PATH];
12693 INT status, size;
12694 HNDLE hKeyInit;
12695 KEY initkey, key;
12696
12697 /* avoid compiler warnings */
12698 status = level;
12699
12700 /* compose name of init key */
12701 std::string s = db_get_path(hDB, hKey);
12702 mstrlcpy(full_name, s.c_str(), sizeof(full_name));
12703 *strchr(full_name, 'O') = 'I';
12704
12705 /* if key in init record found, copy original data to init data */
12706 status = db_find_key(hDB, 0, full_name, &hKeyInit);
12707 if (status == DB_SUCCESS) {
12708 status = db_get_key(hDB, hKeyInit, &initkey);
12709 if (status != DB_SUCCESS) {
12710 cm_msg(MERROR, "merge_records", "merge_record error at \'%s\', db_get_key() status %d", full_name, status);
12711 return;
12712 }
12714 if (status != DB_SUCCESS) {
12715 cm_msg(MERROR, "merge_records", "merge_record error at \'%s\', second db_get_key() status %d", full_name, status);
12716 return;
12717 }
12718
12719 if (initkey.type != TID_KEY && initkey.type == key.type) {
12720 char* allocbuffer = NULL;
12721 char stackbuffer[10000];
12722 char* buffer = stackbuffer;
12723 size = sizeof(stackbuffer);
12724 while (1) {
12725 /* copy data from original key to new key */
12726 status = db_get_data(hDB, hKey, buffer, &size, initkey.type);
12727 if (status == DB_SUCCESS) {
12728 status = db_set_data(hDB, hKeyInit, buffer, initkey.total_size, initkey.num_values, initkey.type);
12729 if (status != DB_SUCCESS) {
12730 cm_msg(MERROR, "merge_records", "merge_record error at \'%s\', db_set_data() status %d", full_name, status);
12731 return;
12732 }
12733 break;
12734 }
12735 if (status == DB_TRUNCATED) {
12736 size *= 2;
12737 allocbuffer = (char *)realloc(allocbuffer, size);
12738 assert(allocbuffer != NULL);
12739 buffer = allocbuffer;
12740 continue;
12741 }
12742 cm_msg(MERROR, "merge_records", "aborting on unexpected failure of db_get_data(%s), status %d", full_name, status);
12743 abort();
12744 }
12745 if (allocbuffer)
12746 free(allocbuffer);
12747 }
12748 } else if (status == DB_NO_KEY) {
12749 /* do nothing */
12750 } else if (status == DB_INVALID_LINK) {
12751 status = db_find_link(hDB, 0, full_name, &hKeyInit);
12752 if (status == DB_SUCCESS) {
12753 size = sizeof(full_name);
12754 status = db_get_data(hDB, hKeyInit, full_name, &size, TID_LINK);
12755 }
12756 cm_msg(MERROR, "merge_records", "Invalid link \"%s\"", full_name);
12757 } else {
12758 cm_msg(MERROR, "merge_records", "aborting on unexpected failure of db_find_key(%s), status %d", full_name, status);
12759 abort();
12760 }
12761}
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 9115 of file odb.cxx.

9123{
9124 if (*str >= '0' && *str <= '9')
9125 *str = '_';
9126
9127 while (*str) {
9128 if (!(*str >= 'a' && *str <= 'z') && !(*str >= 'A' && *str <= 'Z') && !(*str >= '0' && *str <= '9'))
9129 *str = '_';
9130 *str = (char) tolower(*str);
9131 str++;
9132 }
9133}
Here is the caller graph for this function:

◆ print_key_info_locked()

static INT print_key_info_locked ( const DATABASE_HEADER pheader,
const KEY pkey,
INT  level,
void *  info,
db_err_msg **  msg 
)
static

Definition at line 685 of file odb.cxx.

686{
687 std::string* pbuf = (std::string*)info;
688
689 HNDLE hKey = db_pkey_to_hkey(pheader, pkey);
690
691 *pbuf += msprintf("%9d %9d %9d ",
692 (int) (hKey - sizeof(DATABASE_HEADER)),
693 (int) (pkey->data - sizeof(DATABASE_HEADER)), (int) pkey->total_size);
694
695 for (int i = 0; i < level; i++)
696 *pbuf += " ";
697
698 *pbuf += pkey->name;
699 *pbuf += "\n";
700
701 return SUCCESS;
702}
#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 597 of file odb.cxx.

598{
599 void *tmp = NULL;
600
601 if (old_size) {
602 int status;
603 tmp = malloc(old_size);
604 if (tmp == NULL) {
605 cm_msg(MERROR, "realloc_data", "cannot malloc(%d), called from %s", old_size, caller);
606 return NULL;
607 }
608
609 memcpy(tmp, address, old_size);
610
611 status = free_data(pheader, address, old_size, caller);
612 if (status != DB_SUCCESS) {
613 free(tmp);
614 cm_msg(MERROR, "realloc_data", "cannot free_data(%p, %d), called from %s", address, old_size, caller);
615 return NULL;
616 }
617 }
618
619 void *pnew = malloc_data(pheader, new_size);
620
621 if (!pnew) {
622 if (tmp)
623 free(tmp);
624 cm_msg(MERROR, "realloc_data", "cannot malloc_data(%d), called from %s", new_size, caller);
625 return NULL;
626 }
627
628 if (old_size) {
629 memcpy(pnew, tmp, old_size < new_size ? old_size : new_size);
630 free(tmp);
631 }
632
633 return pnew;
634}
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 3357 of file odb.cxx.

3357 {
3358 char* pc;
3359
3360 *index1 = *index2 = 0;
3361 if (odbpath[strlen(odbpath) - 1] == ']') {
3362 if (strchr(odbpath, '[')) {
3363 if (*(strchr(odbpath, '[') + 1) == '*')
3364 *index1 = -1;
3365 else if (strchr((strchr(odbpath, '[') + 1), '.') ||
3366 strchr((strchr(odbpath, '[') + 1), '-')) {
3367 *index1 = atoi(strchr(odbpath, '[') + 1);
3368 pc = strchr(odbpath, '[') + 1;
3369 while (*pc != '.' && *pc != '-')
3370 pc++;
3371 while (*pc == '.' || *pc == '-')
3372 pc++;
3373 *index2 = atoi(pc);
3374 } else
3375 *index1 = atoi(strchr(odbpath, '[') + 1);
3376 }
3377
3378 //remove everything after bracket
3379 *strchr(odbpath, '[') = 0;
3380 }
3381}
Here is the caller graph for this function:

◆ strcomb()

char EXPRT * strcomb ( const char **  list)

Definition at line 639 of file odb.cxx.

641{
642 INT i, j;
643 static char *str = NULL;
644
645 /* counter number of chars */
646 for (i = 0, j = 0; list[i]; i++)
647 j += strlen(list[i]) + 1;
648 j += 1;
649
650 if (str == NULL)
651 str = (char *) malloc(j);
652 else
653 str = (char *) realloc(str, j);
654
655 assert(str != NULL);
656
657 str[0] = 0;
658 for (i = 0; list[i]; i++) {
659 strcat(str, list[i]);
660 strcat(str, "\n");
661 }
662
663 return str;
664}
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 668 of file odb.cxx.

670{
671 std::string s;
672
673 for (int i = 0; list[i]; i++) {
674 s += list[i];
675 s += "\n";
676 }
677
678 return s;
679}
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 3319 of file odb.cxx.

3319 {
3320 switch(*pattern){
3321 case 0:
3322 if(*str == 0){
3323 //end of pattern
3324 return true;
3325 }else
3326 return false;
3327 case '*':
3328 {
3329 int i=0;
3330 // check for end of the string
3331 if(pattern[1] == 0) return true;
3332 // loop on all possible matches
3333 while(str[i] != 0) if(strmatch(pattern + 1, str+(i++))) return true;
3334 return false;
3335 }
3336 case '?':
3337 if(*str == 0){
3338 //end of string
3339 return false;
3340 } else {
3341 return strmatch(pattern+1, str+1);
3342 }
3343 default:
3344 if(*str == 0){
3345 //end of string
3346 return false;
3347 } else if(toupper(*str) == toupper(*pattern)){
3348 //recursion
3349 return strmatch(pattern+1, str+1);
3350 } else {
3351 return false;
3352 }
3353 }
3354}
Here is the call graph for this function:
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 404 of file odb.cxx.

405{
406 if (free_data <= 0)
407 return 0;
408
409 if (free_data < (int)sizeof(DATABASE_HEADER)) {
410 //printf("validate_free_data: failed: %d is inside the database header 0..%d\n", free_data, (int)sizeof(DATABASE_HEADER));
411 return 0;
412 }
413
414 if (free_data < (int)sizeof(DATABASE_HEADER) + pheader->key_size) {
415 //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);
416 return 0;
417 }
418
419 if (free_data > (int)sizeof(DATABASE_HEADER) + pheader->key_size + pheader->data_size) {
420 //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);
421 return 0;
422 }
423
424 return 1;
425}
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 9321 of file odb.cxx.

9322{
9323 int i;
9324 char *dst, *p;
9325
9326 dst = (char *) malloc(size);
9327 if (dst == NULL)
9328 return;
9329
9330 *dst = 0;
9331 for (i = 0; i < (int) strlen(src); i++) {
9332 switch (src[i]) {
9333 case '<':
9334 mstrlcat(dst, "&lt;", size);
9335 break;
9336 case '>':
9337 mstrlcat(dst, "&gt;", size);
9338 break;
9339 case '&':
9340 mstrlcat(dst, "&amp;", size);
9341 break;
9342 case '\"':
9343 mstrlcat(dst, "&quot;", size);
9344 break;
9345 case '\'':
9346 mstrlcat(dst, "&apos;", size);
9347 break;
9348 default:
9349 if ((int) strlen(dst) >= size) {
9350 free(dst);
9351 return;
9352 }
9353 p = dst + strlen(dst);
9354 *p = src[i];
9355 *(p + 1) = 0;
9356 }
9357 }
9358
9359 mstrlcpy(src, dst, size);
9360}

Variable Documentation

◆ _database

DATABASE* _database
static

Definition at line 54 of file odb.cxx.

◆ _database_entries

INT _database_entries = 0
static

Definition at line 55 of file odb.cxx.

◆ _global_open_count

int _global_open_count
static

Definition at line 12763 of file odb.cxx.

◆ _last_error_message

db_err_msg* _last_error_message = NULL
static

Definition at line 132 of file odb.cxx.

◆ _record_list

RECORD_LIST* _record_list
static

Definition at line 58 of file odb.cxx.

◆ _record_list_entries

INT _record_list_entries = 0
static

Definition at line 59 of file odb.cxx.

◆ _watch_list

WATCH_LIST* _watch_list
static

Definition at line 61 of file odb.cxx.

◆ _watch_list_entries

INT _watch_list_entries = 0
static

Definition at line 62 of file odb.cxx.