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_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 1894 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 12512 of file odb.cxx.

12513{
12514 if (pkey->notify_count)
12516}
static int _global_open_count
Definition odb.cxx:12510
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 12140 of file odb.cxx.

12148{
12149 if (rpc_is_remote())
12150 return rpc_call(RPC_DB_ADD_OPEN_RECORD, hDB, hKey, access_mode);
12151
12152#ifdef LOCAL_ROUTINES
12153 {
12154 INT i;
12155 int status;
12156
12157 if (hDB > _database_entries || hDB <= 0) {
12158 cm_msg(MERROR, "db_add_open_record", "invalid database handle");
12159 return DB_INVALID_HANDLE;
12160 }
12161
12162 db_err_msg* msg = NULL;
12163
12164 /* lock database */
12166
12167 DATABASE *pdb = &_database[hDB - 1];
12168 DATABASE_HEADER *pheader = pdb->database_header;
12170
12171 /* check if key is already open */
12172 for (i = 0; i < pclient->max_index; i++) {
12173 if (pclient->open_record[i].handle == hKey)
12174 break;
12175 }
12176
12177 if (i < pclient->max_index) {
12179 return DB_SUCCESS;
12180 }
12181
12182 /* not found, search free entry */
12183 for (i = 0; i < pclient->max_index; i++) {
12184 if (pclient->open_record[i].handle == 0)
12185 break;
12186 }
12187
12188 /* check if maximum number reached */
12189 if (i == MAX_OPEN_RECORDS) {
12191 return DB_NO_MEMORY;
12192 }
12193
12194 db_allow_write_locked(pdb, "db_add_open_record");
12195
12196 KEY *pkey = (KEY*)db_get_pkey(pheader, hKey, &status, "db_add_open_record", &msg);
12197
12198 if (!pkey) {
12200 if (msg)
12201 db_flush_msg(&msg);
12202 return status;
12203 }
12204
12205 if (i == pclient->max_index)
12206 pclient->max_index++;
12207
12208 pclient->open_record[i].handle = hKey;
12209 pclient->open_record[i].access_mode = access_mode;
12210
12211 /* increment notify_count */
12212 pkey->notify_count++;
12213
12214 pclient->num_open_records++;
12215
12216 /* set exclusive bit if requested */
12217 if (access_mode & MODE_WRITE)
12219
12221 }
12222#endif /* LOCAL_ROUTINES */
12223
12224 return DB_SUCCESS;
12225}
#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:930
INT db_set_mode(HNDLE hDB, HNDLE hKey, WORD mode, BOOL recurse)
Definition odb.cxx:7787
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:72
bool rpc_is_remote(void)
Definition midas.cxx:12786
INT rpc_call(DWORD routine_id,...)
Definition midas.cxx:13688
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:880
#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 12750 of file odb.cxx.

12751{
12752 char line[MAX_STRING_LENGTH];
12753 char title[MAX_STRING_LENGTH];
12754 char key_name[MAX_STRING_LENGTH];
12755 char info_str[MAX_STRING_LENGTH + 50];
12756 char *pc;
12757 const char *pold, *rec_str_orig;
12758 DWORD tid;
12759 INT i, j, n_data, string_length, status;
12760 HNDLE hKeyRoot, hKeyTest;
12761 KEY key;
12762 int bad_string_length;
12763
12764 if (rpc_is_remote())
12765 return rpc_call(RPC_DB_CHECK_RECORD, hDB, hKey, keyname, rec_str, correct);
12766
12767 /* check if record exists */
12768 status = db_find_key(hDB, hKey, keyname, &hKeyRoot);
12769
12770 /* create record if not */
12771 if (status == DB_NO_KEY) {
12772 if (correct)
12773 return db_create_record(hDB, hKey, keyname, rec_str);
12774 return DB_NO_KEY;
12775 }
12776
12777 assert(hKeyRoot);
12778
12779 title[0] = 0;
12780 rec_str_orig = rec_str;
12781
12782 db_get_key(hDB, hKeyRoot, &key);
12783 if (key.type == TID_KEY)
12784 /* get next subkey which is not of type TID_KEY */
12785 db_get_next_link(hDB, hKeyRoot, &hKeyTest);
12786 else
12787 /* test root key itself */
12788 hKeyTest = hKeyRoot;
12789
12790 if (hKeyTest == 0 && *rec_str != 0) {
12791 if (correct)
12792 return db_create_record(hDB, hKey, keyname, rec_str_orig);
12793
12794 return DB_STRUCT_MISMATCH;
12795 }
12796
12797 do {
12798 if (*rec_str == 0)
12799 break;
12800
12801 for (i = 0; *rec_str != '\n' && *rec_str && i < MAX_STRING_LENGTH; i++)
12802 line[i] = *rec_str++;
12803
12804 if (i == MAX_STRING_LENGTH) {
12805 cm_msg(MERROR, "db_check_record", "line too long");
12806 return DB_TRUNCATED;
12807 }
12808
12809 line[i] = 0;
12810 if (*rec_str == '\n')
12811 rec_str++;
12812
12813 /* check if it is a section title */
12814 if (line[0] == '[') {
12815 /* extract title and append '/' */
12816 strcpy(title, line + 1);
12817 if (strchr(title, ']'))
12818 *strchr(title, ']') = 0;
12819 if (title[0] && title[strlen(title) - 1] != '/')
12820 strcat(title, "/");
12821 } else {
12822 /* valid data line if it includes '=' and no ';' */
12823 if (strchr(line, '=') && line[0] != ';') {
12824 /* copy type info and data */
12825 pc = strchr(line, '=') + 1;
12826 while (*pc == ' ')
12827 pc++;
12828 strcpy(info_str, pc);
12829
12830 /* extract key name */
12831 *strchr(line, '=') = 0;
12832
12833 pc = &line[strlen(line) - 1];
12834 while (*pc == ' ')
12835 *pc-- = 0;
12836
12837 mstrlcpy(key_name, line, sizeof(key_name));
12838
12839 /* evaluate type info */
12840 strcpy(line, info_str);
12841 if (strchr(line, ' '))
12842 *strchr(line, ' ') = 0;
12843
12844 n_data = 1;
12845 if (strchr(line, '[')) {
12846 n_data = atol(strchr(line, '[') + 1);
12847 *strchr(line, '[') = 0;
12848 }
12849
12850 for (tid = 0; tid < TID_LAST; tid++)
12851 if (strcmp(rpc_tid_name(tid), line) == 0)
12852 break;
12853 if (tid == TID_LAST) {
12854 for (tid = 0; tid < TID_LAST; tid++)
12855 if (strcmp(rpc_tid_name_old(tid), line) == 0)
12856 break;
12857 }
12858
12859 string_length = 0;
12860
12861 if (tid == TID_LAST)
12862 cm_msg(MERROR, "db_check_record", "found unknown data type \"%s\" in ODB file", line);
12863 else {
12864 /* skip type info */
12865 pc = info_str;
12866 while (*pc != ' ' && *pc)
12867 pc++;
12868 while ((*pc == ' ' || *pc == ':') && *pc)
12869 pc++;
12870
12871 if (n_data > 1) {
12872 info_str[0] = 0;
12873 if (!*rec_str)
12874 break;
12875
12876 for (j = 0; *rec_str != '\n' && *rec_str; j++)
12877 info_str[j] = *rec_str++;
12878 info_str[j] = 0;
12879 if (*rec_str == '\n')
12880 rec_str++;
12881 }
12882
12883 for (i = 0; i < n_data; i++) {
12884 /* strip trailing \n */
12885 pc = &info_str[strlen(info_str) - 1];
12886 while (*pc == '\n' || *pc == '\r')
12887 *pc-- = 0;
12888
12889 if (tid == TID_STRING || tid == TID_LINK) {
12890 if (!string_length) {
12891 if (info_str[1] == '=')
12892 string_length = -1;
12893 else {
12894 pc = strchr(info_str, '[');
12895 if (pc != NULL)
12896 string_length = atoi(pc + 1);
12897 else
12898 string_length = -1;
12899 }
12900 if (string_length > MAX_STRING_LENGTH) {
12901 string_length = MAX_STRING_LENGTH;
12902 cm_msg(MERROR, "db_check_record", "found string exceeding MAX_STRING_LENGTH");
12903 }
12904 }
12905
12906 if (string_length == -1) {
12907 /* multi-line string */
12908 if (strstr(rec_str, "\n====#$@$#====\n") != NULL) {
12909 string_length = (POINTER_T) strstr(rec_str, "\n====#$@$#====\n") - (POINTER_T) rec_str + 1;
12910
12911 rec_str = strstr(rec_str, "\n====#$@$#====\n") + strlen("\n====#$@$#====\n");
12912 } else
12913 cm_msg(MERROR, "db_check_record", "found multi-line string without termination sequence");
12914 } else {
12915 if (strchr(info_str, ']'))
12916 pc = strchr(info_str, ']') + 1;
12917 else
12918 pc = info_str + 2;
12919 while (*pc && *pc != ' ')
12920 pc++;
12921 while (*pc && *pc == ' ')
12922 pc++;
12923
12924 /* limit string size */
12925 *(pc + string_length - 1) = 0;
12926 }
12927 } else {
12928 pc = info_str;
12929
12930 if (n_data > 1 && info_str[0] == '[') {
12931 pc = strchr(info_str, ']') + 1;
12932 while (*pc && *pc == ' ')
12933 pc++;
12934 }
12935 }
12936
12937 if (i < n_data - 1) {
12938 info_str[0] = 0;
12939 if (!*rec_str)
12940 break;
12941
12942 pold = rec_str;
12943
12944 for (j = 0; *rec_str != '\n' && *rec_str; j++)
12945 info_str[j] = *rec_str++;
12946 info_str[j] = 0;
12947 if (*rec_str == '\n')
12948 rec_str++;
12949
12950 /* test if valid data */
12951 if (tid != TID_STRING && tid != TID_LINK) {
12952 if (info_str[0] == 0 || (strchr(info_str, '=')
12953 && strchr(info_str, ':')))
12954 rec_str = pold;
12955 }
12956 }
12957 }
12958
12959 /* if rec_str contains key, but not ODB, return mismatch */
12960 if (!hKeyTest) {
12961 if (correct)
12962 return db_create_record(hDB, hKey, keyname, rec_str_orig);
12963
12964 return DB_STRUCT_MISMATCH;
12965 }
12966
12967 status = db_get_key(hDB, hKeyTest, &key);
12968 assert(status == DB_SUCCESS);
12969
12970 bad_string_length = 0;
12971
12972 if (key.type == TID_STRING) {
12973 //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);
12974 if (string_length > 0 && string_length != key.item_size) {
12975 bad_string_length = 1;
12976 }
12977 }
12978
12979 /* check rec_str vs. ODB key */
12980 if (!equal_ustring(key.name, key_name) || key.type != tid || key.num_values != n_data || bad_string_length) {
12981 //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);
12982 if (correct)
12983 return db_create_record(hDB, hKey, keyname, rec_str_orig);
12984
12985 return DB_STRUCT_MISMATCH;
12986 }
12987
12988 /* get next key in ODB */
12989 db_get_next_link(hDB, hKeyTest, &hKeyTest);
12990 }
12991 }
12992 }
12993 } while (TRUE);
12994
12995 return DB_SUCCESS;
12996}
#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:5587
INT db_get_key(HNDLE hDB, HNDLE hKey, KEY *key)
Definition odb.cxx:5790
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:12578
const char * rpc_tid_name_old(INT id)
Definition midas.cxx:11796
const char * rpc_tid_name(INT id)
Definition midas.cxx:11789
#define RPC_DB_CHECK_RECORD
Definition mrpc.h:89
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 6919 of file odb.cxx.

6920{
6921 /* check for write access */
6922 if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
6923 return DB_NO_ACCESS;
6924 }
6925
6926 if (pkey->type != type) {
6927 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));
6928 return DB_TYPE_MISMATCH;
6929 }
6930
6931 /* keys cannot contain data */
6932 if (pkey->type == TID_KEY) {
6933 db_msg(msg, MERROR, "db_set_data_index", "\"%s\" of type TID_KEY cannot contain data", db_get_path_pkey(pheader, pkey).c_str());
6934 return DB_TYPE_MISMATCH;
6935 }
6936
6937 /* check utf-8 encoding */
6938 if (pkey->type == TID_STRING || pkey->type == TID_LINK) {
6939 //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);
6940 const char* value = (const char*)data;
6941 if (!is_utf8(value)) {
6942 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);
6943 // just a warning for now. K.O.
6944 //return DB_TYPE_MISMATCH;
6945 }
6946 }
6947
6948 /* check for valid idx */
6949 if (idx < 0) {
6950 db_msg(msg, MERROR, caller, "\%s\" given invalid index %d", db_get_path_pkey(pheader, pkey).c_str(), idx);
6951 return DB_INVALID_PARAM;
6952 }
6953
6954 /* check for valid array element size: if new element size
6955 is different from existing size, ODB becomes corrupted */
6956 if (pkey->item_size != 0 && data_size != pkey->item_size) {
6957 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);
6958 return DB_TYPE_MISMATCH;
6959 }
6960
6961 return DB_SUCCESS;
6962}
#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 6872 of file odb.cxx.

6873{
6874 /* check for write access */
6875 if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
6876 return DB_NO_ACCESS;
6877 }
6878
6879 if (pkey->type != type) {
6880 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));
6881 return DB_TYPE_MISMATCH;
6882 }
6883
6884 /* keys cannot contain data */
6885 if (pkey->type == TID_KEY) {
6886 db_msg(msg, MERROR, caller, "\"%s\" of type TID_KEY cannot contain data", db_get_path_pkey(pheader, pkey).c_str());
6887 return DB_TYPE_MISMATCH;
6888 }
6889
6890 if (type == TID_STRING || type == TID_LINK) {
6891 if (num_values > 1) {
6892 int item_size = pkey->item_size;
6893 if (data_size > 0 && num_values > 0)
6894 item_size = data_size/num_values;
6895 //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);
6896 for (int i=0; i<num_values; i++) {
6897 const char* value = ((const char*)data) + i * item_size;
6898 //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);
6899 if (!is_utf8(value)) {
6900 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);
6901 // just a warning for now. K.O.
6902 //return DB_TYPE_MISMATCH;
6903 }
6904 }
6905 } else {
6906 const char* value = (const char*)data;
6907 //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);
6908 if (!is_utf8(value)) {
6909 db_msg(msg, MERROR, caller, "\"%s\" set to invalid UTF-8 Unicode string value \"%s\"", db_get_path_pkey(pheader, pkey).c_str(), value);
6910 // just a warning for now. K.O.
6911 //return DB_TYPE_MISMATCH;
6912 }
6913 }
6914 }
6915
6916 return DB_SUCCESS;
6917}
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:13293
INT db_unwatch_all()
Definition odb.cxx:13697
INT db_close_database(HNDLE hDB)
Definition odb.cxx:2190
#define RPC_DB_CLOSE_ALL_DATABASES
Definition mrpc.h:54
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_close_all_records()

INT db_close_all_records ( void  )

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

Returns
DB_SUCCESS, DB_INVALID_HANDLE

Definition at line 13293 of file odb.cxx.

13294{
13295 INT i;
13296
13297 for (i = 0; i < _record_list_entries; i++) {
13298 if (_record_list[i].handle) {
13299 if (_record_list[i].access_mode & MODE_WRITE) {
13300 free(_record_list[i].copy);
13301 _record_list[i].copy = NULL;
13302 }
13303
13304 if (_record_list[i].access_mode & MODE_ALLOC) {
13305 free(_record_list[i].data);
13306 _record_list[i].data = NULL;
13307 }
13308
13309 memset(&_record_list[i], 0, sizeof(RECORD_LIST));
13310 }
13311 }
13312
13313 if (_record_list_entries > 0) {
13315 free(_record_list);
13316 _record_list = NULL;
13317 }
13318
13319 return DB_SUCCESS;
13320}
#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:12229
#define RPC_DB_CLOSE_DATABASE
Definition mrpc.h:53
INT _semaphore_alarm
Definition midas.cxx:1477
INT _semaphore_elog
Definition midas.cxx:1478
INT _semaphore_history
Definition midas.cxx:1479
#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 13252 of file odb.cxx.

13253{
13254#ifdef LOCAL_ROUTINES
13255 {
13256 INT i;
13257
13258 for (i = 0; i < _record_list_entries; i++)
13259 if (_record_list[i].handle == hKey && _record_list[i].hDB == hDB)
13260 break;
13261
13262 if (i == _record_list_entries)
13263 return DB_INVALID_HANDLE;
13264
13265 /* remove record entry from database structure */
13267
13268 /* free local memory */
13269 if (_record_list[i].access_mode & MODE_ALLOC) {
13270 free(_record_list[i].data);
13271 _record_list[i].data = NULL;
13272 }
13273
13274 if (_record_list[i].access_mode & MODE_WRITE) {
13275 free(_record_list[i].copy);
13276 _record_list[i].copy = NULL;
13277 }
13278
13279 memset(&_record_list[i], 0, sizeof(RECORD_LIST));
13280 }
13281#endif /* LOCAL_ROUTINES */
13282
13283 return DB_SUCCESS;
13284}
INT db_remove_open_record(HNDLE hDB, HNDLE hKey, BOOL lock)
Definition odb.cxx:12275
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 7977 of file odb.cxx.

7978{
7979 INT i, j, size, status;
7980 KEY key;
7981 HNDLE hSubkey;
7982 char *data;
7983
7984 //printf("db_copy: %d %d %p %d [%s]\n", hDB, hKey, buffer, *buffer_size, path);
7985
7986 std::string full_path = path;
7987
7988 if (full_path.length() > MAX_ODB_PATH) {
7989 cm_msg(MERROR, "db_copy", "ODB path too long at \"%s\"", path);
7990 return DB_NO_MEMORY;
7991 }
7992
7993 BOOL bWritten = FALSE;
7994
7995 /* first enumerate this level */
7996 for (i = 0;; i++) {
7998
7999 if (i == 0 && !hSubkey) {
8000 std::string line;
8001
8002 /* If key has no subkeys, just write this key */
8004 if (status != DB_SUCCESS)
8005 continue;
8006 size = key.total_size;
8007 data = (char *) malloc(size);
8008 if (data == NULL) {
8009 cm_msg(MERROR, "db_copy", "cannot allocate data buffer");
8010 return DB_NO_MEMORY;
8011 }
8012
8013 if (key.type != TID_KEY) {
8015 if (status != DB_SUCCESS)
8016 continue;
8017 if (key.num_values == 1) {
8018 line = msprintf("%s = %s : ", key.name, rpc_tid_name(key.type));
8019
8020 if (key.type == TID_STRING && strchr(data, '\n') != NULL) {
8021 /* multiline string */
8022 line += "[====#$@$#====]\n";
8023
8024 /* copy line to buffer */
8025 if ((INT) (line.length() + 1) > *buffer_size) {
8026 free(data);
8027 return DB_TRUNCATED;
8028 }
8029
8030 strcpy(buffer, line.c_str());
8031 buffer += line.length();
8032 *buffer_size -= line.length();
8033
8034 /* copy multiple lines to buffer */
8035 if (key.item_size > *buffer_size) {
8036 free(data);
8037 return DB_TRUNCATED;
8038 }
8039
8040 strcpy(buffer, data);
8041 buffer += strlen(data);
8042 *buffer_size -= strlen(data);
8043
8044 line = "\n====#$@$#====\n";
8045 } else {
8046 std::string str = db_sprintf(data, key.item_size, 0, key.type);
8047
8048 if (key.type == TID_STRING || key.type == TID_LINK)
8049 line += msprintf("[%d] ", key.item_size);
8050
8051 line += str + "\n";
8052 }
8053 } else {
8054 line = msprintf("%s = %s[%d] :\n", key.name, rpc_tid_name(key.type), key.num_values);
8055
8056 for (j = 0; j < key.num_values; j++) {
8057 if (key.type == TID_STRING || key.type == TID_LINK)
8058 line += msprintf("[%d] ", key.item_size);
8059 else
8060 line += msprintf("[%d] ", j);
8061
8062 std::string str = db_sprintf(data, key.item_size, j, key.type);
8063 line += str + "\n";
8064
8065 /* copy line to buffer */
8066 if ((INT) (line.length() + 1) > *buffer_size) {
8067 free(data);
8068 return DB_TRUNCATED;
8069 }
8070
8071 strcpy(buffer, line.c_str());
8072 buffer += line.length();
8073 *buffer_size -= line.length();
8074 line.clear();
8075 }
8076 }
8077 }
8078
8079 /* copy line to buffer */
8080 if ((INT) (line.length() + 1) > *buffer_size) {
8081 free(data);
8082 return DB_TRUNCATED;
8083 }
8084
8085 strcpy(buffer, line.c_str());
8086 buffer += line.length();
8087 *buffer_size -= line.length();
8088
8089 free(data);
8090 data = NULL;
8091 }
8092
8093 if (!hSubkey)
8094 break;
8095
8097 if (status != DB_SUCCESS)
8098 continue;
8099
8100 if (strcmp(key.name, "arr2") == 0)
8101 printf("\narr2\n");
8102 size = key.total_size;
8103 data = (char *) malloc(size);
8104 if (data == NULL) {
8105 cm_msg(MERROR, "db_copy", "cannot allocate data buffer");
8106 return DB_NO_MEMORY;
8107 }
8108
8109 if (key.type == TID_KEY) {
8110 char str[MAX_ODB_PATH];
8111
8112 /* new line */
8113 if (bWritten) {
8114 if (*buffer_size < 2) {
8115 free(data);
8116 return DB_TRUNCATED;
8117 }
8118
8119 strcpy(buffer, "\n");
8120 buffer += 1;
8121 *buffer_size -= 1;
8122 }
8123
8124 strcpy(str, full_path.c_str());
8125 if (str[0] && str[strlen(str) - 1] != '/')
8126 strcat(str, "/");
8127 strcat(str, key.name);
8128
8129 /* recurse */
8130 status = db_copy(hDB, hSubkey, buffer, buffer_size, str);
8131 if (status != DB_SUCCESS) {
8132 free(data);
8133 return status;
8134 }
8135
8136 buffer += strlen(buffer);
8137 bWritten = FALSE;
8138 } else {
8139 std::string line;
8140
8142 if (status != DB_SUCCESS)
8143 continue;
8144
8145 if (!bWritten) {
8146 if (path[0] == 0)
8147 line = "[.]\n";
8148 else
8149 line = msprintf("[%s]\n", path);
8150 bWritten = TRUE;
8151 }
8152
8153 if (key.num_values == 1) {
8154 line += msprintf("%s = %s : ", key.name, rpc_tid_name(key.type));
8155
8156 if (key.type == TID_STRING && strchr(data, '\n') != NULL) {
8157 /* multiline string */
8158 line += "[====#$@$#====]\n";
8159
8160 /* ensure string limiter */
8161 data[size - 1] = 0;
8162
8163 /* copy line to buffer */
8164 if ((INT) (line.length() + 1) > *buffer_size) {
8165 free(data);
8166 return DB_TRUNCATED;
8167 }
8168
8169 strcpy(buffer, line.c_str());
8170 buffer += line.length();
8171 *buffer_size -= line.length();
8172
8173 /* copy multiple lines to buffer */
8174 if (key.item_size > *buffer_size) {
8175 free(data);
8176 return DB_TRUNCATED;
8177 }
8178
8179 strcpy(buffer, data);
8180 buffer += strlen(data);
8181 *buffer_size -= strlen(data);
8182
8183 line = "\n====#$@$#====\n";
8184 } else {
8185 std::string str = db_sprintf(data, key.item_size, 0, key.type);
8186
8187 if (key.type == TID_STRING || key.type == TID_LINK)
8188 line += msprintf("[%d] ", key.item_size);
8189
8190 line += str + "\n";
8191 }
8192 } else {
8193 line += msprintf("%s = %s[%d] :\n", key.name, rpc_tid_name(key.type), key.num_values);
8194
8195 for (j = 0; j < key.num_values; j++) {
8196 if (key.type == TID_STRING || key.type == TID_LINK)
8197 line += msprintf("[%d] ", key.item_size);
8198 else
8199 line += msprintf("[%d] ", j);
8200
8201 std::string str = db_sprintf(data, key.item_size, j, key.type);
8202 line += str + "\n";
8203
8204 /* copy line to buffer */
8205 if ((INT) (line.length() + 1) > *buffer_size) {
8206 free(data);
8207 return DB_TRUNCATED;
8208 }
8209
8210 strcpy(buffer, line.c_str());
8211 buffer += line.length();
8212 *buffer_size -= line.length();
8213 line.clear();
8214 }
8215 }
8216
8217 /* copy line to buffer */
8218 if ((INT) (line.length() + 1) > *buffer_size) {
8219 free(data);
8220 return DB_TRUNCATED;
8221 }
8222
8223 strcpy(buffer, line.c_str());
8224 buffer += line.length();
8225 *buffer_size -= line.length();
8226 }
8227
8228 free(data);
8229 data = NULL;
8230 }
8231
8232 if (bWritten) {
8233 if (*buffer_size < 2)
8234 return DB_TRUNCATED;
8235
8236 strcpy(buffer, "\n");
8237 buffer += 1;
8238 *buffer_size -= 1;
8239 }
8240
8241 return DB_SUCCESS;
8242}
INT db_copy(HNDLE hDB, HNDLE hKey, char *buffer, INT *buffer_size, const char *path)
Definition odb.cxx:7977
INT db_get_link(HNDLE hDB, HNDLE hKey, KEY *key)
Definition odb.cxx:5843
INT db_enum_link(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
Definition odb.cxx:5496
INT db_sprintf(char *string, const void *data, INT data_size, INT idx, DWORD type)
Definition odb.cxx:10612
INT db_get_link_data(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, DWORD type)
Definition odb.cxx:6427
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 9920 of file odb.cxx.

9921{
9922 int size, asize;
9923 int status;
9924 char* data;
9925 int i;
9926 KEY key;
9927
9929 if (status != DB_SUCCESS)
9930 return status;
9931
9932 assert(key.type != TID_KEY);
9933
9934 if (key.num_values > 1) {
9935 json_write(buffer, buffer_size, buffer_end, 0, "[ ", 0);
9936 }
9937
9938 size = key.total_size;
9939
9940 asize = size;
9941 if (asize < 1024)
9942 asize = 1024;
9943
9944 data = (char *) malloc(asize);
9945 if (data == NULL) {
9946 cm_msg(MERROR, "db_save_json_key_data", "cannot allocate data buffer for %d bytes", asize);
9947 return DB_NO_MEMORY;
9948 }
9949
9950 data[0] = 0; // protect against TID_STRING that has key.total_size == 0.
9951
9952 status = db_get_data(hDB, hKey, data, &size, key.type);
9953 if (status != DB_SUCCESS) {
9954 free(data);
9955 return status;
9956 }
9957
9958 for (i = 0; i < key.num_values; i++) {
9959 char *p = data + key.item_size*i;
9960
9961 if (i != 0)
9962 json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9963
9964 json_write_data(buffer, buffer_size, buffer_end, 0, &key, p);
9965 }
9966
9967 if (key.num_values > 1) {
9968 json_write(buffer, buffer_size, buffer_end, 0, " ]", 0);
9969 }
9970
9971 free(data);
9972 data = NULL;
9973
9974 return DB_SUCCESS;
9975}
INT db_get_data(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, DWORD type)
Definition odb.cxx:6310
static void json_write_data(char **buffer, int *buffer_size, int *buffer_end, int level, const KEY *key, const char *p)
Definition odb.cxx:9412
void json_write(char **buffer, int *buffer_size, int *buffer_end, int level, const char *s, int quoted)
Definition odb.cxx:9297
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 9989 of file odb.cxx.

9990{
9991 int status;
9992 KEY key;
9993
9995
9996 if (status != DB_SUCCESS)
9997 return status;
9998
9999 int size = key.item_size;
10000 char* data = (char*)malloc(size + 1); // extra byte for string NUL termination
10001 assert(data != NULL);
10002
10004
10005 if (status != DB_SUCCESS) {
10006 free(data);
10007 return status;
10008 }
10009
10010 assert(size <= key.item_size);
10011 data[key.item_size] = 0; // make sure data is NUL terminated, in case of strings.
10012
10013 json_write_data(buffer, buffer_size, buffer_end, 0, &key, data);
10014
10015 free(data);
10016
10017 return DB_SUCCESS;
10018}
INT db_get_data_index(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT idx, DWORD type)
Definition odb.cxx:6664
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 10189 of file odb.cxx.

10190{
10191 int status;
10192 bool unlock = false;
10193
10194 if (!rpc_is_remote()) {
10196 if (status != DB_SUCCESS) {
10197 return status;
10198 }
10199 unlock = true;
10200 }
10201
10203
10204 if (unlock) {
10206 }
10207
10208 return status;
10209}
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:10152
#define JS_LEVEL_0
Definition midas.h:1718
#define JSFLAG_FOLLOW_LINKS
Definition midas.h:1722
#define JS_MUST_BE_SUBDIR
Definition midas.h:1720
#define JSFLAG_SAVE_KEYS
Definition midas.h:1721
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 10276 of file odb.cxx.

10277{
10278 db_save_json_key_obsolete(hDB, hKey, 0, buffer, buffer_size, buffer_end, save_keys, follow_links, recurse);
10279 json_write(buffer, buffer_size, buffer_end, 0, "\n", 0);
10280 return DB_SUCCESS;
10281}
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:9581
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 10243 of file odb.cxx.

10244{
10245 int status;
10246 bool unlock = false;
10247
10248 if (!rpc_is_remote()) {
10250 if (status != DB_SUCCESS) {
10251 return status;
10252 }
10253 unlock = true;
10254 }
10255
10257
10258 if (unlock) {
10260 }
10261
10262 return status;
10263}
#define JSFLAG_RECURSE
Definition midas.h:1723
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 10211 of file odb.cxx.

10212{
10213 int status;
10215 if (omit_names)
10216 flags |= JSFLAG_OMIT_NAMES;
10217 if (omit_last_written)
10218 flags |= JSFLAG_OMIT_LAST_WRITTEN;
10219 if (omit_old_timestamp)
10220 flags |= JSFLAG_OMIT_OLD;
10221 if (!preserve_case)
10222 flags |= JSFLAG_LOWERCASE;
10223
10224 bool unlock = false;
10225
10226 if (!rpc_is_remote()) {
10228 if (status != DB_SUCCESS) {
10229 return status;
10230 }
10231 unlock = true;
10232 }
10233
10234 status = json_write_anything(hDB, hKey, buffer, buffer_size, buffer_end, JS_LEVEL_0, 0, flags, omit_old_timestamp);
10235
10236 if (unlock) {
10238 }
10239
10240 return status;
10241}
#define JSFLAG_LOWERCASE
Definition midas.h:1724
#define JSFLAG_OMIT_LAST_WRITTEN
Definition midas.h:1726
#define JSFLAG_OMIT_NAMES
Definition midas.h:1725
#define JSFLAG_OMIT_OLD
Definition midas.h:1727
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 8802 of file odb.cxx.

8803{
8804
8805 if (rpc_is_remote())
8806 return rpc_call(RPC_DB_COPY_XML, hDB, hKey, buffer, buffer_size, header);
8807
8808#ifdef LOCAL_ROUTINES
8809 {
8810 INT len;
8811 char *p;
8812 MXML_WRITER *writer;
8813
8814 /* open file */
8815 writer = mxml_open_buffer();
8816 if (writer == NULL) {
8817 cm_msg(MERROR, "db_copy_xml", "Cannot allocate buffer");
8818 return DB_NO_MEMORY;
8819 }
8820
8821 if (header) {
8822 std::string path = db_get_path(hDB, hKey);
8823
8824 /* write XML header */
8825 mxml_start_element(writer, "odb");
8826 mxml_write_attribute(writer, "root", path.c_str());
8827 mxml_write_attribute(writer, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
8828 mxml_write_attribute(writer, "xsi:noNamespaceSchemaLocation", "http://midas.psi.ch/odb.xsd");
8829
8830 db_save_xml_key(hDB, hKey, 0, writer);
8831 mxml_end_element(writer); // "odb"
8832 } else {
8833 KEY key;
8834 int status = db_get_key(hDB, hKey, &key);
8835 if (status != DB_SUCCESS)
8836 return status;
8837
8838 db_save_xml_key(hDB, hKey, 1, writer);
8839 }
8840
8841 p = mxml_close_buffer(writer);
8842 len = strlen(p) + 1;
8843 if (len > *buffer_size) {
8844 free(p);
8845 *buffer_size = 0;
8846 return DB_TRUNCATED;
8847 }
8848
8849 mstrlcpy(buffer, p, len);
8850 free(p);
8851 *buffer_size = len;
8852 }
8853#endif /* LOCAL_ROUTINES */
8854
8855 return DB_SUCCESS;
8856}
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:9111
#define RPC_DB_COPY_XML
Definition mrpc.h:98
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_create_key()

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

Create a new key in a database

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

Definition at line 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:55
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_create_key_wlocked()

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

Definition at line 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:11782
#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:7196
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:56
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_create_record()

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

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

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

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

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

struct {
INT level1;
INT level2;
char *trigger_settings_str =
"[Settings]\n\
level1 = INT : 0\n\
level2 = INT : 0";
void trigger_update(INT hDB, INT hkey, void *info)
{
printf("New levels: %d %d\n",
}
{
HNDLE hDB, hkey;
char[128] info;
...
db_create_record(hDB, 0, "/Equipment/Trigger", trigger_settings_str);
db_find_key(hDB, 0,"/Equipment/Trigger/Settings", &hkey);
sizeof(trigger_settings), MODE_READ, trigger_update, info);
...
}
TRIGGER_SETTINGS trigger_settings
Definition analyzer.cxx:52
INT cm_get_experiment_database(HNDLE *hDB, HNDLE *hKeyClient)
Definition midas.cxx:3026
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:13069
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 12578 of file odb.cxx.

12579{
12580 char key_name[256], *buffer;
12581 INT status, size, buffer_size;
12582 HNDLE hKeyTmp, hKeyTmpO, hKeyOrig, hSubkey;
12583
12584 if (rpc_is_remote())
12585 return rpc_call(RPC_DB_CREATE_RECORD, hDB, hKey, orig_key_name, init_str);
12586
12587 /* make this function atomic */
12589
12590 /* strip trailing '/' */
12591 mstrlcpy(key_name, orig_key_name, sizeof(key_name));
12592 if (strlen(key_name) > 1 && key_name[strlen(key_name) - 1] == '/')
12593 key_name[strlen(key_name) - 1] = 0;
12594
12595 /* merge temporay record and original record */
12596 status = db_find_key(hDB, hKey, key_name, &hKeyOrig);
12597 if (status == DB_SUCCESS) {
12598 assert(hKeyOrig != 0);
12599#ifdef CHECK_OPEN_RECORD
12600 /* check if key or subkey is opened */
12601 _global_open_count = 0; // FIXME: this is not thread safe
12602 db_scan_tree_link(hDB, hKeyOrig, 0, check_open_keys, NULL);
12603 if (_global_open_count) {
12605 return DB_OPEN_RECORD;
12606 }
12607#endif
12608 /* create temporary records */
12609 std::string str = "/System/Tmp/" + ss_tid_to_string(ss_gettid()) + "I";
12610 //printf("db_create_record str [%s]\n", str);
12611 db_delete(hDB, 0, str.c_str());
12612 db_create_key(hDB, 0, str.c_str(), TID_KEY);
12613 status = db_find_key(hDB, 0, str.c_str(), &hKeyTmp);
12614 if (status != DB_SUCCESS) {
12616 return status;
12617 }
12618
12619 str = "/System/Tmp/" + ss_tid_to_string(ss_gettid()) + "O";
12620 //printf("db_create_record str [%s]\n", str);
12621 db_delete(hDB, 0, str.c_str());
12622 db_create_key(hDB, 0, str.c_str(), TID_KEY);
12623 status = db_find_key(hDB, 0, str.c_str(), &hKeyTmpO);
12624 if (status != DB_SUCCESS) {
12626 return status;
12627 }
12628
12629 status = db_paste(hDB, hKeyTmp, init_str);
12630 if (status != DB_SUCCESS) {
12632 return status;
12633 }
12634
12635 buffer_size = 10000;
12636 buffer = (char *) malloc(buffer_size);
12637 assert(buffer != NULL);
12638
12639 do {
12640 size = buffer_size;
12641 status = db_copy(hDB, hKeyOrig, buffer, &size, "");
12642 if (status == DB_TRUNCATED) {
12643 buffer_size += 10000;
12644 buffer = (char *) realloc(buffer, buffer_size);
12645 assert(buffer != NULL);
12646 continue;
12647 }
12648 if (status != DB_SUCCESS) {
12649 free(buffer);
12651 return status;
12652 }
12653
12654 } while (status != DB_SUCCESS);
12655
12656 status = db_paste(hDB, hKeyTmpO, buffer);
12657 if (status != DB_SUCCESS) {
12658 free(buffer);
12660 return status;
12661 }
12662
12663 /* merge temporay record and original record */
12664 db_scan_tree_link(hDB, hKeyTmpO, 0, merge_records, NULL);
12665
12666 /* delete original record */
12667 while (1) {
12668 db_enum_link(hDB, hKeyOrig, 0, &hSubkey);
12669 if (!hSubkey)
12670 break;
12671
12673 if (status != DB_SUCCESS) {
12674 free(buffer);
12676 return status;
12677 }
12678 }
12679
12680 /* copy merged record to original record */
12681 do {
12682 size = buffer_size;
12683 status = db_copy(hDB, hKeyTmp, buffer, &size, "");
12684 if (status == DB_TRUNCATED) {
12685 buffer_size += 10000;
12686 buffer = (char *) realloc(buffer, buffer_size);
12687 continue;
12688 }
12689 if (status != DB_SUCCESS) {
12690 free(buffer);
12692 return status;
12693 }
12694
12695 } while (status != DB_SUCCESS);
12696
12697 status = db_paste(hDB, hKeyOrig, buffer);
12698 if (status != DB_SUCCESS) {
12699 free(buffer);
12701 return status;
12702 }
12703
12704 /* delete temporary records */
12705 db_delete_key(hDB, hKeyTmp);
12706 db_delete_key(hDB, hKeyTmpO);
12707
12708 free(buffer);
12709 buffer = NULL;
12710 } else if (status == DB_NO_KEY) {
12711 /* create fresh record */
12712 db_create_key(hDB, hKey, key_name, TID_KEY);
12713 status = db_find_key(hDB, hKey, key_name, &hKeyTmp);
12714 if (status != DB_SUCCESS) {
12716 return status;
12717 }
12718
12719 status = db_paste(hDB, hKeyTmp, init_str);
12720 if (status != DB_SUCCESS) {
12722 return status;
12723 }
12724 } else {
12725 cm_msg(MERROR, "db_create_record", "aborting on unexpected failure of db_find_key(%s), status %d", key_name, status);
12726 abort();
12727 }
12728
12730
12731 return DB_SUCCESS;
12732}
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:12512
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:8252
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:12437
#define RPC_DB_CREATE_RECORD
Definition mrpc.h:80
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_delete()

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:7739
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:62
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_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_find_key", 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);
}
INT db_enum_key(HNDLE hDB, HNDLE hKey, INT idx, HNDLE *subkey_handle)
Definition odb.cxx:5357
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 char str[256];
5367 HNDLE parent;
5368
5369 if (hDB > _database_entries || hDB <= 0) {
5370 cm_msg(MERROR, "db_enum_key", "invalid database handle");
5371 return DB_INVALID_HANDLE;
5372 }
5373
5374 if (!_database[hDB - 1].attached) {
5375 cm_msg(MERROR, "db_enum_key", "invalid database handle");
5376 return DB_INVALID_HANDLE;
5377 }
5378
5379 *subkey_handle = 0;
5380
5381 /* first lock database */
5383
5384 pheader = _database[hDB - 1].database_header;
5385 if (!hKey)
5386 hKey = pheader->root_key;
5387
5388 /* check if hKey argument is correct */
5389 if (!db_validate_hkey(pheader, hKey)) {
5391 return DB_INVALID_HANDLE;
5392 }
5393
5394 db_err_msg *msg = NULL;
5395 int status;
5396
5397 const KEY* pkey = db_get_pkey(pheader, hKey, &status, "db_enum_key", &msg);
5398
5399 if (!pkey) {
5401 db_flush_msg(&msg);
5402 return DB_NO_MORE_SUBKEYS;
5403 }
5404
5405 if (pkey->type != TID_KEY) {
5407 return DB_NO_MORE_SUBKEYS;
5408 }
5409
5410 const KEYLIST* pkeylist = db_get_pkeylist(pheader, pkey, "db_enum_key", &msg);
5411
5412 if (!pkeylist) {
5414 db_flush_msg(&msg);
5415 return DB_NO_MORE_SUBKEYS;
5416 }
5417
5418 if (idx >= pkeylist->num_keys) {
5420 return DB_NO_MORE_SUBKEYS;
5421 }
5422
5423 pkey = db_get_pkey(pheader, pkeylist->first_key, &status, "db_enum_key", &msg);
5424
5425 if (!pkey) {
5426 std::string path = db_get_path_locked(pheader, hKey);
5427 HNDLE xfirst_key = pkeylist->first_key;
5429 if (msg)
5430 db_flush_msg(&msg);
5431 cm_msg(MERROR, "db_enum_key", "hkey %d path \"%s\" invalid first_key %d", hKey, path.c_str(), xfirst_key);
5432 return DB_NO_MORE_SUBKEYS;
5433 }
5434
5435 for (i = 0; i < idx; i++) {
5436 if (pkey->next_key == 0) {
5437 std::string path = db_get_path_locked(pheader, hKey);
5439 cm_msg(MERROR, "db_enum_key", "hkey %d path \"%s\" unexpected end of key list at index %d", hKey, path.c_str(), i);
5440 return DB_NO_MORE_SUBKEYS;
5441 }
5442
5443 pkey = db_get_pkey(pheader, pkey->next_key, &status, "db_enum_key", &msg);
5444
5445 if (!pkey) {
5446 std::string path = db_get_path_locked(pheader, hKey);
5448 db_flush_msg(&msg);
5449 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);
5450 return DB_NO_MORE_SUBKEYS;
5451 }
5452 }
5453
5454 /* resolve links */
5455 if (pkey->type == TID_LINK) {
5456 strcpy(str, (char *) pheader + pkey->data);
5457
5458 /* no not resolve if link to array index */
5459 if (strlen(str) > 0 && str[strlen(str) - 1] == ']') {
5460 *subkey_handle = (POINTER_T) pkey - (POINTER_T) pheader;
5462 return DB_SUCCESS;
5463 }
5464
5465 if (*str == '/') {
5466 /* absolute path */
5468 return db_find_key(hDB, 0, str, subkey_handle);
5469 } else {
5470 /* relative path */
5471 if (pkey->parent_keylist) {
5472 pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
5473 parent = pkeylist->parent;
5475 return db_find_key(hDB, parent, str, subkey_handle);
5476 } else {
5478 return db_find_key(hDB, 0, str, subkey_handle);
5479 }
5480 }
5481 }
5482
5483 *subkey_handle = (POINTER_T) pkey - (POINTER_T) pheader;
5485 }
5486#endif /* LOCAL_ROUTINES */
5487
5488 return DB_SUCCESS;
5489}
#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:63
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 5496 of file odb.cxx.

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

◆ db_enum_next_locked()

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

Definition at line 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:59
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:60
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:84
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_flush_msg()

void db_flush_msg ( db_err_msg **  msg)
static

Definition at line 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 6310 of file odb.cxx.

6311{
6312 if (rpc_is_remote())
6313 return rpc_call(RPC_DB_GET_DATA, hDB, hKey, data, buf_size, type);
6314
6315#ifdef LOCAL_ROUTINES
6316 {
6317 int status;
6318
6319 if (hDB > _database_entries || hDB <= 0) {
6320 cm_msg(MERROR, "db_get_data", "Invalid database handle");
6321 return DB_INVALID_HANDLE;
6322 }
6323
6324 if (!_database[hDB - 1].attached) {
6325 cm_msg(MERROR, "db_get_data", "invalid database handle");
6326 return DB_INVALID_HANDLE;
6327 }
6328
6329 if (hKey < (int) sizeof(DATABASE_HEADER)) {
6330 cm_msg(MERROR, "db_get_data", "invalid key handle");
6331 return DB_INVALID_HANDLE;
6332 }
6333
6335
6337 db_err_msg* msg = NULL;
6338
6339 const KEY* pkey = db_get_pkey(pheader, hKey, &status, "db_get_data", &msg);
6340
6341 if (!pkey) {
6343 if (msg)
6344 db_flush_msg(&msg);
6345 return status;
6346 }
6347
6348 /* check for read access */
6349 if (!(pkey->access_mode & MODE_READ)) {
6351 if (msg)
6352 db_flush_msg(&msg);
6353 return DB_NO_ACCESS;
6354 }
6355
6356 /* follow links to array index */
6357 if (pkey->type == TID_LINK) {
6358 std::string link_name = (char *) pheader + pkey->data;
6359 if (link_name.length() > 0 && link_name.back() == ']') {
6360 size_t pos = link_name.rfind("[");
6361 if (pos == std::string::npos) {
6362 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());
6364 if (msg)
6365 db_flush_msg(&msg);
6366 return DB_INVALID_LINK;
6367 }
6368 int idx = atoi(link_name.c_str()+pos+1);
6369 link_name.resize(pos);
6370 //printf("link name [%s] idx %d\n", link_name.c_str(), idx);
6371
6372 // relative symlinks did not work in the old db_get_data(), make sure they do not work now. K.O.
6373 if (link_name[0] != '/') {
6374 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());
6376 if (msg)
6377 db_flush_msg(&msg);
6378 return DB_INVALID_LINK;
6379 }
6380
6381 const KEY* pkey = db_find_pkey_locked(pheader, NULL, link_name.c_str(), true, &status, &msg);
6382
6383 if (!pkey) {
6385 if (msg)
6386 db_flush_msg(&msg);
6387 return status;
6388 }
6389
6390 //printf("db_get_data [%s] type [%s] idx %d\n", db_get_path_pkey(pheader, pkey).c_str(), rpc_tid_name(type), idx);
6391
6392 status = db_get_data_locked(pheader, pkey, idx, data, buf_size, type, &msg);
6393
6395 if (msg)
6396 db_flush_msg(&msg);
6397 return status;
6398 }
6399 }
6400
6401 //printf("db_get_data [%s] type [%s]\n", db_get_path_pkey(pheader, pkey).c_str(), rpc_tid_name(type));
6402
6403 status = db_get_data_locked(pheader, pkey, -1, data, buf_size, type, &msg);
6404
6406 if (msg)
6407 db_flush_msg(&msg);
6408
6409 return status;
6410 }
6411#endif /* LOCAL_ROUTINES */
6412
6413 return DB_SUCCESS;
6414}
#define RPC_DB_GET_DATA
Definition mrpc.h:65
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_data1()

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

dox

Definition at line 6527 of file odb.cxx.

6552{
6553 if (rpc_is_remote())
6554 return rpc_call(RPC_DB_GET_DATA1, hDB, hKey, data, buf_size, type, num_values);
6555
6556#ifdef LOCAL_ROUTINES
6557 {
6558 DATABASE_HEADER *pheader;
6559 KEY *pkey;
6560
6561 if (hDB > _database_entries || hDB <= 0) {
6562 cm_msg(MERROR, "db_get_data", "Invalid database handle");
6563 return DB_INVALID_HANDLE;
6564 }
6565
6566 if (!_database[hDB - 1].attached) {
6567 cm_msg(MERROR, "db_get_data", "invalid database handle");
6568 return DB_INVALID_HANDLE;
6569 }
6570
6571 if (hKey < (int) sizeof(DATABASE_HEADER)) {
6572 cm_msg(MERROR, "db_get_data", "invalid key handle");
6573 return DB_INVALID_HANDLE;
6574 }
6575
6577
6578 pheader = _database[hDB - 1].database_header;
6579
6580 /* check if hKey argument is correct */
6581 if (!db_validate_hkey(pheader, hKey)) {
6583 return DB_INVALID_HANDLE;
6584 }
6585
6586 pkey = (KEY *) ((char *) pheader + hKey);
6587
6588 /* check for read access */
6589 if (!(pkey->access_mode & MODE_READ)) {
6591 return DB_NO_ACCESS;
6592 }
6593
6594 if (!pkey->type) {
6595 int pkey_type = pkey->type;
6597 cm_msg(MERROR, "db_get_data", "hkey %d invalid key type %d", hKey, pkey_type);
6598 return DB_INVALID_HANDLE;
6599 }
6600
6601 if (pkey->type != type) {
6602 int pkey_type = pkey->type;
6603 char pkey_name[NAME_LENGTH];
6604 mstrlcpy(pkey_name, pkey->name, sizeof(pkey_name));
6606 cm_msg(MERROR, "db_get_data", "\"%s\" is of type %s, not %s", pkey_name, rpc_tid_name(pkey_type), rpc_tid_name(type));
6607 return DB_TYPE_MISMATCH;
6608 }
6609
6610 /* keys cannot contain data */
6611 if (pkey->type == TID_KEY) {
6613 cm_msg(MERROR, "db_get_data", "Key cannot contain data");
6614 return DB_TYPE_MISMATCH;
6615 }
6616
6617 /* check if key has data */
6618 if (pkey->data == 0) {
6619 memset(data, 0, *buf_size);
6620 *buf_size = 0;
6622 return DB_SUCCESS;
6623 }
6624
6625 /* check if buffer is too small */
6626 if (pkey->num_values * pkey->item_size > *buf_size) {
6627 int pkey_size = pkey->num_values * pkey->item_size;
6628 memcpy(data, (char *) pheader + pkey->data, *buf_size);
6630 std::string path = db_get_path(hDB, hKey);
6631 cm_msg(MERROR, "db_get_data", "data for key \"%s\" truncated from %d to %d bytes", path.c_str(), pkey_size, *buf_size);
6632 return DB_TRUNCATED;
6633 }
6634
6635 /* copy key data */
6636 memcpy(data, (char *) pheader + pkey->data, pkey->num_values * pkey->item_size);
6637 *buf_size = pkey->num_values * pkey->item_size;
6638 *num_values = pkey->num_values;
6639
6641
6642 }
6643#endif /* LOCAL_ROUTINES */
6644
6645 return DB_SUCCESS;
6646}
#define RPC_DB_GET_DATA1
Definition mrpc.h:87
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_data_index()

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

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

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

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

Definition at line 6664 of file odb.cxx.

6665{
6666 if (rpc_is_remote())
6667 return rpc_call(RPC_DB_GET_DATA_INDEX, hDB, hKey, data, buf_size, idx, type);
6668
6669#ifdef LOCAL_ROUTINES
6670 {
6671 DATABASE_HEADER *pheader;
6672 KEY *pkey;
6673
6674 if (hDB > _database_entries || hDB <= 0) {
6675 cm_msg(MERROR, "db_get_data", "Invalid database handle");
6676 return DB_INVALID_HANDLE;
6677 }
6678
6679 if (!_database[hDB - 1].attached) {
6680 cm_msg(MERROR, "db_get_data", "invalid database handle");
6681 return DB_INVALID_HANDLE;
6682 }
6683
6684 if (hKey < (int) sizeof(DATABASE_HEADER)) {
6685 cm_msg(MERROR, "db_get_data", "invalid key handle");
6686 return DB_INVALID_HANDLE;
6687 }
6688
6690
6691 pheader = _database[hDB - 1].database_header;
6692
6693 /* check if hKey argument is correct */
6694 if (!db_validate_hkey(pheader, hKey)) {
6696 return DB_INVALID_HANDLE;
6697 }
6698
6699 pkey = (KEY *) ((char *) pheader + hKey);
6700
6701 /* check for read access */
6702 if (!(pkey->access_mode & MODE_READ)) {
6704 return DB_NO_ACCESS;
6705 }
6706
6707 if (!pkey->type) {
6708 int pkey_type = pkey->type;
6710 cm_msg(MERROR, "db_get_data_index", "hkey %d invalid key type %d", hKey, pkey_type);
6711 return DB_INVALID_HANDLE;
6712 }
6713
6714 if (pkey->type != type) {
6715 int pkey_type = pkey->type;
6716 char pkey_name[NAME_LENGTH];
6717 mstrlcpy(pkey_name, pkey->name, sizeof(pkey_name));
6719 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));
6720 return DB_TYPE_MISMATCH;
6721 }
6722
6723 /* keys cannot contain data */
6724 if (pkey->type == TID_KEY) {
6726 cm_msg(MERROR, "db_get_data_index", "Key cannot contain data");
6727 return DB_TYPE_MISMATCH;
6728 }
6729
6730 /* check if key has data */
6731 if (pkey->data == 0) {
6732 memset(data, 0, *buf_size);
6733 *buf_size = 0;
6735 return DB_SUCCESS;
6736 }
6737
6738 /* check if index in range */
6739 if (idx < 0 || idx >= pkey->num_values) {
6740 int pkey_num_values = pkey->num_values;
6741 memset(data, 0, *buf_size);
6743
6744 std::string path = db_get_path(hDB, hKey);
6745 cm_msg(MERROR, "db_get_data_index", "index (%d) exceeds array length (%d) for key \"%s\"", idx, pkey_num_values, path.c_str());
6746 return DB_OUT_OF_RANGE;
6747 }
6748
6749 /* check if buffer is too small */
6750 if (pkey->item_size > *buf_size) {
6751 int pkey_size = pkey->item_size;
6752 /* copy data */
6753 memcpy(data, (char *) pheader + pkey->data + idx * pkey->item_size, *buf_size);
6755 std::string path = db_get_path(hDB, hKey);
6756 cm_msg(MERROR, "db_get_data_index", "data for key \"%s\" truncated from %d to %d bytes", path.c_str(), pkey_size, *buf_size);
6757 return DB_TRUNCATED;
6758 }
6759
6760 /* copy key data */
6761 memcpy(data, (char *) pheader + pkey->data + idx * pkey->item_size, pkey->item_size);
6762 *buf_size = pkey->item_size;
6763
6765
6766 }
6767#endif /* LOCAL_ROUTINES */
6768
6769 return DB_SUCCESS;
6770}
#define DB_OUT_OF_RANGE
Definition midas.h:652
#define RPC_DB_GET_DATA_INDEX
Definition mrpc.h:81
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_data_locked()

static INT db_get_data_locked ( DATABASE_HEADER pheader,
const KEY pkey,
int  idx,
void *  data,
INT buf_size,
DWORD  type,
db_err_msg **  msg 
)
static

Definition at line 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 5790 of file odb.cxx.

5791{
5792 if (rpc_is_remote())
5793 return rpc_call(RPC_DB_GET_KEY, hDB, hKey, key);
5794
5795#ifdef LOCAL_ROUTINES
5796 {
5797 DATABASE_HEADER *pheader;
5798 int status;
5799
5800 if (hDB > _database_entries || hDB <= 0) {
5801 cm_msg(MERROR, "db_get_key", "invalid database handle");
5802 return DB_INVALID_HANDLE;
5803 }
5804
5805 if (!_database[hDB - 1].attached) {
5806 cm_msg(MERROR, "db_get_key", "invalid database handle");
5807 return DB_INVALID_HANDLE;
5808 }
5809
5810 if (hKey < (int) sizeof(DATABASE_HEADER) && hKey != 0) {
5811 cm_msg(MERROR, "db_get_key", "invalid key handle");
5812 return DB_INVALID_HANDLE;
5813 }
5814
5815 db_err_msg *msg = NULL;
5816
5818
5819 pheader = _database[hDB - 1].database_header;
5820
5821 status = db_get_key_locked(pheader, hKey, key, &msg);
5822
5824
5825 if (msg)
5826 db_flush_msg(&msg);
5827
5828 return status;
5829 }
5830#endif /* LOCAL_ROUTINES */
5831
5832 return DB_SUCCESS;
5833}
static INT db_get_key_locked(const DATABASE_HEADER *pheader, HNDLE hKey, KEY *key, db_err_msg **msg)
Definition odb.cxx:5713
#define RPC_DB_GET_KEY
Definition mrpc.h:64
Here is the call graph for this function:

◆ db_get_key_info()

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

Get key info (separate values instead of structure)

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

Definition at line 5962 of file odb.cxx.

5963{
5964 if (rpc_is_remote())
5965 return rpc_call(RPC_DB_GET_KEY_INFO, hDB, hKey, name, name_size, type, num_values, item_size);
5966
5967#ifdef LOCAL_ROUTINES
5968 {
5969 DATABASE_HEADER *pheader;
5970 KEY *pkey;
5971 KEYLIST *pkeylist;
5972
5973 if (hDB > _database_entries || hDB <= 0) {
5974 cm_msg(MERROR, "db_get_key_info", "invalid database handle");
5975 return DB_INVALID_HANDLE;
5976 }
5977
5978 if (!_database[hDB - 1].attached) {
5979 cm_msg(MERROR, "db_get_key_info", "invalid database handle");
5980 return DB_INVALID_HANDLE;
5981 }
5982
5983 if (hKey < (int) sizeof(DATABASE_HEADER)) {
5984 cm_msg(MERROR, "db_get_key_info", "invalid key handle");
5985 return DB_INVALID_HANDLE;
5986 }
5987
5989
5990 pheader = _database[hDB - 1].database_header;
5991
5992 /* check if hKey argument is correct */
5993 if (!db_validate_hkey(pheader, hKey)) {
5995 return DB_INVALID_HANDLE;
5996 }
5997
5998 pkey = (KEY *) ((char *) pheader + hKey);
5999
6000 if ((INT) strlen(pkey->name) + 1 > name_size) {
6001 /* truncate name */
6002 memcpy(name, pkey->name, name_size - 1);
6003 name[name_size] = 0;
6004 } else
6005 strcpy(name, pkey->name);
6006
6007 /* convert "root" to "/" */
6008 if (strcmp(name, "root") == 0)
6009 strcpy(name, "/");
6010
6011 *type = pkey->type;
6012 *num_values = pkey->num_values;
6013 *item_size = pkey->item_size;
6014
6015 if (pkey->type == TID_KEY) {
6016 pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
6017 *num_values = pkeylist->num_keys;
6018 }
6019
6021 }
6022#endif /* LOCAL_ROUTINES */
6023
6024 return DB_SUCCESS;
6025}
#define RPC_DB_GET_KEY_INFO
Definition mrpc.h:86
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_key_locked()

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

dox

Definition at line 5713 of file odb.cxx.

5714{
5715 if (!hKey)
5716 hKey = pheader->root_key;
5717
5718 /* check if hKey argument is correct */
5719 if (!db_validate_hkey(pheader, hKey)) {
5720 return DB_INVALID_HANDLE;
5721 }
5722
5723 const KEY* pkey = (const KEY *) ((char *) pheader + hKey);
5724
5725 if (pkey->type < 1 || pkey->type >= TID_LAST) {
5726 int pkey_type = pkey->type;
5727 db_msg(msg, MERROR, "db_get_key", "hkey %d invalid key type %d", hKey, pkey_type);
5728 return DB_INVALID_HANDLE;
5729 }
5730
5731 /* check for link to array index */
5732 if (pkey->type == TID_LINK) {
5733 char link_name[MAX_ODB_PATH];
5734 mstrlcpy(link_name, (char *) pheader + pkey->data, sizeof(link_name));
5735 if (strlen(link_name) > 0 && link_name[strlen(link_name) - 1] == ']') {
5736 if (strchr(link_name, '[') == NULL)
5737 return DB_INVALID_LINK;
5738
5739 HNDLE hkeylink;
5740 if (db_find_key_locked(pheader, 0, link_name, true, &hkeylink, msg) != DB_SUCCESS)
5741 return DB_INVALID_LINK;
5742 int status = db_get_key_locked(pheader, hkeylink, key, msg);
5743 key->num_values = 1; // fake number of values
5744 return status;
5745 }
5746 }
5747
5748 memcpy(key, pkey, sizeof(KEY));
5749
5750 return DB_SUCCESS;
5751}
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 5903 of file odb.cxx.

5904{
5905 if (rpc_is_remote())
5906 return rpc_call(RPC_DB_GET_KEY_TIME, hDB, hKey, delta);
5907
5908#ifdef LOCAL_ROUTINES
5909 {
5910 DATABASE_HEADER *pheader;
5911 KEY *pkey;
5912
5913 if (hDB > _database_entries || hDB <= 0) {
5914 cm_msg(MERROR, "db_get_key", "invalid database handle");
5915 return DB_INVALID_HANDLE;
5916 }
5917
5918 if (!_database[hDB - 1].attached) {
5919 cm_msg(MERROR, "db_get_key", "invalid database handle");
5920 return DB_INVALID_HANDLE;
5921 }
5922
5923 if (hKey < (int) sizeof(DATABASE_HEADER)) {
5924 cm_msg(MERROR, "db_get_key", "invalid key handle");
5925 return DB_INVALID_HANDLE;
5926 }
5927
5929
5930 pheader = _database[hDB - 1].database_header;
5931
5932 /* check if hKey argument is correct */
5933 if (!db_validate_hkey(pheader, hKey)) {
5935 return DB_INVALID_HANDLE;
5936 }
5937
5938 pkey = (KEY *) ((char *) pheader + hKey);
5939
5940 *delta = ss_time() - pkey->last_written;
5941
5943
5944 }
5945#endif /* LOCAL_ROUTINES */
5946
5947 return DB_SUCCESS;
5948}
#define RPC_DB_GET_KEY_TIME
Definition mrpc.h:82
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 5843 of file odb.cxx.

5844{
5845 if (rpc_is_remote())
5846 return rpc_call(RPC_DB_GET_LINK, hDB, hKey, key);
5847
5848#ifdef LOCAL_ROUTINES
5849 {
5850 DATABASE_HEADER *pheader;
5851
5852 if (hDB > _database_entries || hDB <= 0) {
5853 cm_msg(MERROR, "db_get_link", "invalid database handle");
5854 return DB_INVALID_HANDLE;
5855 }
5856
5857 if (!_database[hDB - 1].attached) {
5858 cm_msg(MERROR, "db_get_link", "invalid database handle");
5859 return DB_INVALID_HANDLE;
5860 }
5861
5862 if (hKey < (int) sizeof(DATABASE_HEADER) && hKey != 0) {
5863 cm_msg(MERROR, "db_get_link", "invalid key handle");
5864 return DB_INVALID_HANDLE;
5865 }
5866
5867 db_err_msg *msg = NULL;
5868
5870
5871 pheader = _database[hDB - 1].database_header;
5872
5873 int status = DB_SUCCESS;
5874
5875 const KEY* pkey = db_get_pkey(pheader, hKey, &status, "db_get_link", &msg);
5876 if (pkey) {
5877 memcpy(key, pkey, sizeof(KEY));
5878 } else {
5879 memset(key, 0, sizeof(KEY));
5880 //abort();
5881 }
5882
5884
5885 if (msg)
5886 db_flush_msg(&msg);
5887
5888 return status;
5889 }
5890#endif /* LOCAL_ROUTINES */
5891
5892 return DB_SUCCESS;
5893}
#define RPC_DB_GET_LINK
Definition mrpc.h:91
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_link_data()

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

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

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

Definition at line 6427 of file odb.cxx.

6428{
6429 if (rpc_is_remote())
6430 return rpc_call(RPC_DB_GET_LINK_DATA, hDB, hKey, data, buf_size, type);
6431
6432#ifdef LOCAL_ROUTINES
6433 {
6434 DATABASE_HEADER *pheader;
6435 KEY *pkey;
6436
6437 if (hDB > _database_entries || hDB <= 0) {
6438 cm_msg(MERROR, "db_get_data", "Invalid database handle");
6439 return DB_INVALID_HANDLE;
6440 }
6441
6442 if (!_database[hDB - 1].attached) {
6443 cm_msg(MERROR, "db_get_data", "invalid database handle");
6444 return DB_INVALID_HANDLE;
6445 }
6446
6447 if (hKey < (int) sizeof(DATABASE_HEADER)) {
6448 cm_msg(MERROR, "db_get_data", "invalid key handle");
6449 return DB_INVALID_HANDLE;
6450 }
6451
6453
6454 pheader = _database[hDB - 1].database_header;
6455
6456 /* check if hKey argument is correct */
6457 if (!db_validate_hkey(pheader, hKey)) {
6459 return DB_INVALID_HANDLE;
6460 }
6461
6462 pkey = (KEY *) ((char *) pheader + hKey);
6463
6464 /* check for read access */
6465 if (!(pkey->access_mode & MODE_READ)) {
6467 return DB_NO_ACCESS;
6468 }
6469
6470 if (!pkey->type) {
6471 int pkey_type = pkey->type;
6473 cm_msg(MERROR, "db_get_data", "hkey %d invalid key type %d", hKey, pkey_type);
6474 return DB_INVALID_HANDLE;
6475 }
6476
6477 if (pkey->type != type) {
6478 int pkey_type = pkey->type;
6479 char pkey_name[NAME_LENGTH];
6480 mstrlcpy(pkey_name, pkey->name, sizeof(pkey_name));
6482 cm_msg(MERROR, "db_get_data", "\"%s\" is of type %s, not %s", pkey_name, rpc_tid_name(pkey_type), rpc_tid_name(type));
6483 return DB_TYPE_MISMATCH;
6484 }
6485
6486 /* keys cannot contain data */
6487 if (pkey->type == TID_KEY) {
6489 cm_msg(MERROR, "db_get_data", "Key cannot contain data");
6490 return DB_TYPE_MISMATCH;
6491 }
6492
6493 /* check if key has data */
6494 if (pkey->data == 0) {
6495 memset(data, 0, *buf_size);
6496 *buf_size = 0;
6498 return DB_SUCCESS;
6499 }
6500
6501 /* check if buffer is too small */
6502 if (pkey->num_values * pkey->item_size > *buf_size) {
6503 int pkey_size = pkey->num_values * pkey->item_size;
6504 memcpy(data, (char *) pheader + pkey->data, *buf_size);
6506 std::string path = db_get_path(hDB, hKey);
6507 cm_msg(MERROR, "db_get_data", "data for key \"%s\" truncated from %d to %d bytes", path.c_str(), pkey_size, *buf_size);
6508 return DB_TRUNCATED;
6509 }
6510
6511 /* copy key data */
6512 memcpy(data, (char *) pheader + pkey->data, pkey->num_values * pkey->item_size);
6513 *buf_size = pkey->num_values * pkey->item_size;
6514
6516
6517 }
6518#endif /* LOCAL_ROUTINES */
6519
6520 return DB_SUCCESS;
6521}
#define RPC_DB_GET_LINK_DATA
Definition mrpc.h:92
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_my_client_locked()

DATABASE_CLIENT * db_get_my_client_locked ( DATABASE pdb)

Definition at line 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 5587 of file odb.cxx.

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

◆ db_get_open_records()

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

Definition at line 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:83
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_parent() [1/2]

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

Definition at line 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:97
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:61
Here is the call graph for this function:

◆ db_get_path() [2/2]

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

Definition at line 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:11483
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 11483 of file odb.cxx.

11484{
11485 if (rpc_is_remote()) {
11486 align = ss_get_struct_align();
11487 return rpc_call(RPC_DB_GET_RECORD, hDB, hKey, data, buf_size, align);
11488 }
11489#ifdef LOCAL_ROUTINES
11490 {
11491 KEY key;
11492 INT convert_flags, status;
11493 INT total_size;
11494 void *pdata;
11495
11496 if (data && buf_size) {
11497 memset(data, 0x00, *buf_size);
11498 }
11499
11500 convert_flags = 0;
11501
11502 if (!align)
11503 align = ss_get_struct_align();
11504 else {
11505 /* only convert data if called remotely, as indicated by align != 0 */
11506 if (rpc_is_mserver()) {
11507 convert_flags = rpc_get_convert_flags();
11508 }
11509 }
11510
11511 /* check if key has subkeys */
11513 if (status != DB_SUCCESS)
11514 return status;
11515
11516 if (key.type != TID_KEY) {
11517 /* copy single key */
11518 if (key.item_size * key.num_values != *buf_size) {
11519 cm_msg(MERROR, "db_get_record", "struct size mismatch for \"%s\" (expected size: %d, size in ODB: %d * %d = %d)",
11522 }
11523
11524 db_get_data(hDB, hKey, data, buf_size, key.type);
11525
11526 if (convert_flags) {
11527 if (key.num_values > 1)
11529 else
11530 rpc_convert_single(data, key.type, RPC_OUTGOING, convert_flags);
11531 }
11532
11533 return DB_SUCCESS;
11534 }
11535
11536 /* check record size */
11537 db_get_record_size(hDB, hKey, align, &total_size);
11538 if (total_size != *buf_size) {
11539 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);
11541 }
11542
11543 /* get subkey data */
11544 pdata = data;
11545 total_size = 0;
11546
11547 db_err_msg* msg = NULL;
11549 DATABASE *pdb = &_database[hDB - 1];
11550 db_recurse_record_tree_locked(pdb, hKey, &pdata, &total_size, align, NULL, FALSE, convert_flags, &msg);
11552 if (msg)
11553 db_flush_msg(&msg);
11554
11555 //if (total_size != *buf_size) {
11556 // 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);
11557 // //return DB_STRUCT_SIZE_MISMATCH;
11558 //}
11559 }
11560#endif /* LOCAL_ROUTINES */
11561
11562 return DB_SUCCESS;
11563}
#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:11387
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:11208
void rpc_convert_data(void *data, INT tid, INT flags, INT total_size, INT convert_flags)
Definition midas.cxx:11731
bool rpc_is_mserver(void)
Definition midas.cxx:12843
INT rpc_get_convert_flags(void)
Definition midas.cxx:13055
void rpc_convert_single(void *data, INT tid, INT flags, INT convert_flags)
Definition midas.cxx:11706
#define RPC_DB_GET_RECORD
Definition mrpc.h:70
#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 11581 of file odb.cxx.

11582{
11583 int size = *buf_size;
11584 int odb_size = 0;
11585 int status;
11586 //char path[MAX_ODB_PATH];
11587
11588 /* check record size first */
11589
11591 if (status != DB_SUCCESS)
11592 return status;
11593
11594 /* if size mismatch, call repair function */
11595
11596 if (odb_size != size) {
11597 std::string path = db_get_path(hDB, hKey);
11598 cm_msg(MINFO, "db_get_record1", "Fixing ODB \"%s\" struct size mismatch (expected %d, odb size %d)", path.c_str(), size, odb_size);
11599 status = db_create_record(hDB, hKey, "", rec_str);
11600 if (status != DB_SUCCESS)
11601 return status;
11602 }
11603
11604 /* run db_get_record(), if success, we are done */
11605
11606 status = db_get_record(hDB, hKey, data, buf_size, align);
11607 if (status == DB_SUCCESS)
11608 return status;
11609
11610 /* try repair with db_check_record() */
11611
11612 status = db_check_record(hDB, hKey, "", rec_str, TRUE);
11613 if (status != DB_SUCCESS)
11614 return status;
11615
11616 /* verify struct size again, because there can still be a mismatch if there
11617 * are extra odb entries at the end of the record as db_check_record()
11618 * seems to ignore all odb entries past the end of "rec_str". K.O.
11619 */
11620
11622 if (status != DB_SUCCESS)
11623 return status;
11624
11625 std::string path = db_get_path(hDB, hKey);
11626
11627 if (odb_size != size) {
11628 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());
11629 status = db_create_record(hDB, hKey, "", rec_str);
11630 if (status != DB_SUCCESS)
11631 return status;
11632 }
11633
11634 cm_msg(MERROR, "db_get_record1", "repaired struct size mismatch of \"%s\"", path.c_str());
11635
11636 *buf_size = size;
11637 status = db_get_record(hDB, hKey, data, buf_size, align);
11638
11639 return status;
11640}
INT db_check_record(HNDLE hDB, HNDLE hKey, const char *keyname, const char *rec_str, BOOL correct)
Definition odb.cxx:12750
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:11944
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 11944 of file odb.cxx.

11945{
11946 int status = DB_SUCCESS;
11947
11948 printf("db_get_record2!\n");
11949
11950 assert(data != NULL);
11951 assert(xbuf_size != NULL);
11952 assert(*xbuf_size > 0);
11953 assert(correct == 0);
11954
11955 int truncated = 0;
11956#if 1
11957 char* r1 = NULL;
11958 int rs = *xbuf_size;
11959 if (1) {
11960 r1 = (char*)malloc(rs);
11961 assert(r1 != NULL);
11962 memset(data, 0xFF, *xbuf_size);
11963 memset(r1, 0xFF, rs);
11964 //status = db_get_record1(hDB, hKey, r1, &rs, 0, rec_str);
11965 status = db_get_record(hDB, hKey, r1, &rs, 0);
11966 printf("db_get_record status %d\n", status);
11967 }
11968#endif
11969
11970 char* buf_start = (char*)data;
11971 int buf_size = *xbuf_size;
11972
11973 char* buf_ptr = buf_start;
11974 int buf_remain = buf_size;
11975
11976 while (rec_str && *rec_str != 0) {
11977 char title[256];
11978 char key_name[MAX_ODB_PATH];
11979 int tid = 0;
11980 int n_data = 0;
11981 int string_length = 0;
11982 const char* rec_str_next = NULL;
11983
11984 status = db_parse_record(rec_str, &rec_str_next, title, sizeof(title), key_name, sizeof(key_name), &tid, &n_data, &string_length);
11985
11986 //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);
11987
11988 rec_str = rec_str_next;
11989
11990 if (status != DB_SUCCESS) {
11991 return status;
11992 }
11993
11994 if (key_name[0] == 0) {
11995 // skip title strings, comments, etc
11996 continue;
11997 }
11998
11999 status = db_get_record2_read_element(hDB, hKey, key_name, tid, n_data, string_length, buf_start, &buf_ptr, &buf_remain, correct);
12000 if (status == DB_INVALID_PARAM) {
12001 cm_msg(MERROR, "db_get_record2", "error: cannot continue reading odb record because of previous fatal error, status %d", status);
12002 return DB_INVALID_PARAM;
12003 } if (status != DB_SUCCESS) {
12004 truncated = 1;
12005 }
12006
12007 rec_str = rec_str_next;
12008 }
12009
12010 if (r1) {
12011 int ok = -1;
12012 int i;
12013 for (i=0; i<rs; i++) {
12014 if (r1[i] != buf_start[i]) {
12015 ok = i;
12016 break;
12017 }
12018 }
12019 if (ok>=0 || buf_remain>0) {
12020 printf("db_get_record2: miscompare at %d out of %d, buf_remain %d\n", ok, rs, buf_remain);
12021 } else {
12022 printf("db_get_record2: check ok\n");
12023 }
12024 }
12025
12026 if (buf_remain > 0) {
12027 // FIXME: we finished processing the data definition string, but unused space remains in the buffer
12028 return DB_TRUNCATED;
12029 }
12030
12031 if (truncated)
12032 return DB_TRUNCATED;
12033 else
12034 return DB_SUCCESS;
12035}
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:11825
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:11642
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 11825 of file odb.cxx.

11826{
11827 assert(tid > 0);
11828 assert(n_data > 0);
11829 int tsize = rpc_tid_size(tid);
11830 int offset = *buf_ptr - buf_start;
11831 int align = 0;
11832 if (tsize && (offset%tsize != 0)) {
11833 while (offset%tsize != 0) {
11834 align++;
11835 *(*buf_ptr) = 0xFF; // pad bytes for correct data alignement
11836 (*buf_ptr)++;
11837 (*buf_remain)--;
11838 offset++;
11839 }
11840 }
11841 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);
11842 if (tsize > 0) {
11843 int xsize = tsize*n_data;
11844 if (xsize > *buf_remain) {
11845 cm_msg(MERROR, "db_get_record2", "buffer overrun at key \"%s\", size %d, buffer remaining %d", key_name, xsize, *buf_remain);
11846 return DB_INVALID_PARAM;
11847 }
11848 int ysize = xsize;
11849 int status = db_get_value(hDB, hKey, key_name, *buf_ptr, &ysize, tid, FALSE);
11850 //printf("status %d, xsize %d\n", status, xsize);
11851 if (status != DB_SUCCESS) {
11852 cm_msg(MERROR, "db_get_record2", "cannot read \"%s\", db_get_value() status %d", key_name, status);
11853 memset(*buf_ptr, 0, xsize);
11854 *buf_ptr += xsize;
11855 *buf_remain -= xsize;
11856 return status;
11857 }
11858 *buf_ptr += xsize;
11859 *buf_remain -= xsize;
11860 } else if (tid == TID_STRING) {
11861 int xstatus = 0;
11862 int i;
11863 for (i=0; i<n_data; i++) {
11864 int xsize = string_length;
11865 if (xsize > *buf_remain) {
11866 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);
11867 return DB_INVALID_PARAM;
11868 }
11869 std::string xkey_name = msprintf("%s[%d]", key_name, i);
11870 int status = db_get_value(hDB, hKey, xkey_name.c_str(), *buf_ptr, &xsize, tid, FALSE);
11871 //printf("status %d, string length %d, xsize %d, actual len %d\n", status, string_length, xsize, (int)strlen(*buf_ptr));
11872 if (status == DB_TRUNCATED) {
11873 // make sure string is NUL terminated
11874 (*buf_ptr)[string_length-1] = 0;
11875 cm_msg(MERROR, "db_get_record2", "string key \"%s\" index %d, string value was truncated", key_name, i);
11876 } else if (status != DB_SUCCESS) {
11877 cm_msg(MERROR, "db_get_record2", "cannot read string \"%s\"[%d], db_get_value() status %d", key_name, i, status);
11878 memset(*buf_ptr, 0, string_length);
11879 xstatus = status;
11880 }
11881 *buf_ptr += string_length;
11882 *buf_remain -= string_length;
11883 }
11884 if (xstatus != 0) {
11885 return xstatus;
11886 }
11887 } else {
11888 cm_msg(MERROR, "db_get_record2", "cannot read key \"%s\" of unsupported type %d", key_name, tid);
11889 return DB_INVALID_PARAM;
11890 }
11891 return DB_SUCCESS;
11892}
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 11387 of file odb.cxx.

11388{
11389 if (rpc_is_remote()) {
11390 align = ss_get_struct_align();
11391 return rpc_call(RPC_DB_GET_RECORD_SIZE, hDB, hKey, align, buf_size);
11392 }
11393#ifdef LOCAL_ROUTINES
11394 {
11395 KEY key;
11396 INT status, max_align;
11397
11398 if (!align)
11399 align = ss_get_struct_align();
11400
11401 /* check if key has subkeys */
11403 if (status != DB_SUCCESS)
11404 return status;
11405
11406 if (key.type != TID_KEY) {
11407 /* just a single key */
11408 *buf_size = key.item_size * key.num_values;
11409 return DB_SUCCESS;
11410 }
11411
11412 db_err_msg* msg = NULL;
11414
11415 DATABASE *pdb = &_database[hDB - 1];
11416
11417 /* determine record size */
11418 *buf_size = max_align = 0;
11419 db_recurse_record_tree_locked(pdb, hKey, NULL, buf_size, align, &max_align, 0, 0, &msg);
11420
11421 //int tmp = *buf_size;
11422 /* correct for byte padding */
11423 *buf_size = VALIGN(*buf_size, max_align);
11424
11425 //if (tmp != *buf_size) {
11426 // 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);
11427 //}
11428
11430 if (msg)
11431 db_flush_msg(&msg);
11432 }
11433#endif /* LOCAL_ROUTINES */
11434
11435 return DB_SUCCESS;
11436}
#define VALIGN(adr, align)
Definition midas.h:526
#define RPC_DB_GET_RECORD_SIZE
Definition mrpc.h:69
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_get_value()

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

Get value of a single key.

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

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

Definition at line 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:58
BOOL create
Definition mchart.cxx:39
Here is the call graph for this function:

◆ db_get_value_string()

INT EXPRT db_get_value_string ( HNDLE  hdb,
HNDLE  hKeyRoot,
const char *  key_name,
int  index,
std::string *  s,
BOOL  create,
int  create_string_length 
)

Definition at line 13714 of file odb.cxx.

13715{
13716 int status;
13717 int hkey;
13718
13719 //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);
13720
13721 if (index > 0 && create) {
13722 cm_msg(MERROR, "db_get_value_string", "cannot resize odb string arrays, please use db_resize_string() instead");
13723 return DB_OUT_OF_RANGE;
13724 }
13725
13726 status = db_find_key(hdb, hKeyRoot, key_name, &hkey);
13727 if (status == DB_SUCCESS) {
13728 KEY key;
13729 status = db_get_key(hdb, hkey, &key);
13730 if (status != DB_SUCCESS)
13731 return status;
13732 if (index < 0 || index >= key.num_values)
13733 return DB_OUT_OF_RANGE;
13734 int size = key.item_size;
13735 if (size == 0) {
13736 if (s)
13737 *s = "";
13738 //printf("db_get_value_string: return empty string, item_size %d\n", key.item_size);
13739 return DB_SUCCESS;
13740 }
13741 char* buf = (char*)malloc(size);
13742 assert(buf != NULL);
13743 status = db_get_data_index(hdb, hkey, buf, &size, index, TID_STRING);
13744 if (status != DB_SUCCESS) {
13745 free(buf);
13746 return status;
13747 }
13748 if (s)
13749 *s = buf;
13750 free(buf);
13751 //printf("db_get_value_string: return [%s], len %d, item_size %d, size %d\n", s->c_str(), s->length(), key.item_size, size);
13752 return DB_SUCCESS;
13753 } else if (!create) {
13754 // does not exist and not asked to create it
13755 return status;
13756 } else {
13757 //printf("db_get_value_string: creating [%s]\n", key_name);
13758 status = db_create_key(hdb, hKeyRoot, key_name, TID_STRING);
13759 if (status != DB_SUCCESS)
13760 return status;
13761 status = db_find_key(hdb, hKeyRoot, key_name, &hkey);
13762 if (status != DB_SUCCESS)
13763 return status;
13764 assert(s != NULL);
13765 if (create_string_length == 0) {
13766 int size = s->length() + 1; // 1 byte for final \0
13767 status = db_set_data_index(hdb, hkey, s->c_str(), size, index, TID_STRING);
13768 } else {
13769 char* buf = (char*)malloc(create_string_length);
13770 assert(buf);
13771 mstrlcpy(buf, s->c_str(), create_string_length);
13772 status = db_set_data_index(hdb, hkey, buf, create_string_length, index, TID_STRING);
13773 free(buf);
13774 }
13775 if (status != DB_SUCCESS)
13776 return status;
13777 //printf("db_get_value_string: created with value [%s]\n", s->c_str());
13778 return DB_SUCCESS;
13779 }
13780 // NOT REACHED
13781}
INT db_set_data_index(HNDLE hDB, HNDLE hKey, const void *data, INT data_size, INT idx, DWORD type)
Definition odb.cxx:7415
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 7886 of file odb.cxx.

7887{
7888 struct stat stat_buf;
7889 INT hfile, size, n, i, status;
7890 char *buffer;
7891
7892 if (rpc_is_remote() && bRemote)
7893 return rpc_call(RPC_DB_LOAD, hDB, hKeyRoot, filename);
7894
7895 /* open file */
7896 hfile = open(filename, O_RDONLY | O_TEXT, 0644);
7897 if (hfile == -1) {
7898 cm_msg(MERROR, "db_load", "file \"%s\" not found", filename);
7899 return DB_FILE_ERROR;
7900 }
7901
7902 /* allocate buffer with file size */
7903 fstat(hfile, &stat_buf);
7904 size = stat_buf.st_size;
7905 buffer = (char *) malloc(size + 1);
7906
7907 if (buffer == NULL) {
7908 cm_msg(MERROR, "db_load", "cannot allocate ODB load buffer");
7909 close(hfile);
7910 return DB_NO_MEMORY;
7911 }
7912
7913 n = 0;
7914
7915 do {
7916 i = read(hfile, buffer + n, size - n);
7917 if (i <= 0)
7918 break;
7919 n += i;
7920 } while (TRUE);
7921
7922 buffer[n] = 0;
7923
7924 if (strncmp(buffer, "<?xml version=\"1.0\"", 19) == 0) {
7925 status = db_paste_xml(hDB, hKeyRoot, buffer);
7926 if (status != DB_SUCCESS)
7927 printf("Error in file \"%s\"\n", filename);
7928 } else if( buffer[0] == '{'){
7929 if(strrchr(buffer, '}')){
7930 status = db_paste_json(hDB, hKeyRoot, buffer);
7931 } else {
7933 }
7934 } else
7935 status = db_paste(hDB, hKeyRoot, buffer);
7936
7937 close(hfile);
7938 free(buffer);
7939
7940 return status;
7941}
#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:8763
INT EXPRT db_paste_json(HNDLE hDB, HNDLE hKeyRoot, const char *buffer)
#define RPC_DB_LOAD
Definition mrpc.h:75
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 7688 of file odb.cxx.

7713{
7714 HNDLE hKey;
7715 INT status, old_size;
7716
7717 if (num_values == 0)
7718 return DB_INVALID_PARAM;
7719
7720 status = db_find_key(hDB, hKeyRoot, name, &hKey);
7721 if (status != DB_SUCCESS) {
7722 db_create_key(hDB, hKeyRoot, name, type);
7723 status = db_find_key(hDB, hKeyRoot, name, &hKey);
7724 if (status != DB_SUCCESS)
7725 return status;
7726 status = db_set_data(hDB, hKey, data, data_size, num_values, type);
7727 } else {
7728 old_size = data_size;
7729 db_get_data(hDB, hKey, data, &old_size, type);
7730 status = db_set_data(hDB, hKey, data, data_size, num_values, type);
7731 }
7732
7733 return status;
7734}
INT db_set_data(HNDLE hDB, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type)
Definition odb.cxx:6986
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 12372 of file odb.cxx.

12379{
12380 if (rpc_is_remote()) {
12381 cm_msg(MERROR, "db_notify_clients", "db_notify_clients() does not work in remotely connected MIDAS clients");
12382 return DB_INVALID_HANDLE;
12383 }
12384
12385#ifdef LOCAL_ROUTINES
12386 {
12387 db_err_msg* msg = NULL;
12389 if (status != DB_SUCCESS)
12390 return status;
12391 DATABASE* pdb = &_database[hDB - 1];
12392 db_notify_clients_locked(pdb, hKeyMod, index, bWalk, &msg);
12394 if (msg)
12395 db_flush_msg(&msg);
12396 }
12397#endif
12398 return DB_SUCCESS;
12399}
static int db_notify_clients_locked(const DATABASE *pdb, HNDLE hKeyMod, int index, BOOL bWalk, db_err_msg **msg)
Definition odb.cxx:12316
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 12401 of file odb.cxx.

12413{
12414 if (rpc_is_remote())
12415 return rpc_call(RPC_DB_NOTIFY_CLIENTS_ARRAY, hDB, hKeys, size);
12416
12417#ifdef LOCAL_ROUTINES
12418 {
12420 if (status != DB_SUCCESS)
12421 return status;
12422 db_err_msg* msg = NULL;
12423 DATABASE* pdb = &_database[hDB - 1];
12424 int count = size/sizeof(INT);
12425 for (int i=0 ; i<count; i++) {
12426 db_notify_clients_locked(pdb, hKeys[i], -1, TRUE, &msg);
12427 }
12429 if (msg)
12430 db_flush_msg(&msg);
12431 }
12432#endif
12433 return DB_SUCCESS;
12434}
#define RPC_DB_NOTIFY_CLIENTS_ARRAY
Definition mrpc.h:96
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_notify_clients_locked()

static INT db_notify_clients_locked ( const DATABASE pdb,
HNDLE  hKeyMod,
int  index,
BOOL  bWalk,
db_err_msg **  msg 
)
static

Definition at line 12316 of file odb.cxx.

12324{
12325 HNDLE hKey;
12326 KEYLIST *pkeylist;
12327 INT i, j;
12328 int status;
12329
12330 const DATABASE_HEADER* pheader = pdb->database_header;
12331
12332 hKey = hKeyMod;
12333
12334 const KEY* pkey = db_get_pkey(pheader, hKey, &status, "db_notify_clients", msg);
12335
12336 if (!pkey) {
12337 return status;
12338 }
12339
12340 do {
12341
12342 /* check which client has record open */
12343 if (pkey->notify_count)
12344 for (i = 0; i < pheader->max_client_index; i++) {
12345 const DATABASE_CLIENT* pclient = &pheader->client[i];
12346 for (j = 0; j < pclient->max_index; j++)
12347 if (pclient->open_record[j].handle == hKey) {
12348 /* send notification to remote process */
12349 std::string str = msprintf("O %d %d %d %d", pdb->hDB, hKey, hKeyMod, index);
12350 ss_resume(pclient->port, str.c_str());
12351 }
12352 }
12353
12354 if (pkey->parent_keylist == 0 || !bWalk)
12355 return DB_SUCCESS;
12356
12357 // FIXME: validate pkey->parent_keylist
12358 pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
12359 pkey = db_get_pkey(pheader, pkeylist->parent, &status, "db_notify_clients", msg);
12360 if (!pkey) {
12361 return status;
12362 }
12363 hKey = db_pkey_to_hkey(pheader, pkey);
12364 } while (TRUE);
12365
12366}
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:3340
#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:52
#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 13069 of file odb.cxx.

13071{
13072 INT idx, status, size;
13073 KEY key;
13074 void *data;
13075
13076 /* allocate new space for the local record list */
13077 if (_record_list_entries == 0) {
13078 _record_list = (RECORD_LIST *) malloc(sizeof(RECORD_LIST));
13079 assert(_record_list != NULL);
13080 memset(_record_list, 0, sizeof(RECORD_LIST));
13081 if (_record_list == NULL) {
13082 cm_msg(MERROR, "db_open_record", "not enough memory");
13083 return DB_NO_MEMORY;
13084 }
13085
13087 idx = 0;
13088 } else {
13089 /* check for a deleted entry */
13090 for (idx = 0; idx < _record_list_entries; idx++)
13091 if (!_record_list[idx].handle)
13092 break;
13093
13094 /* if not found, create new one */
13095 if (idx == _record_list_entries) {
13097 if (_record_list == NULL) {
13098 cm_msg(MERROR, "db_open_record", "not enough memory");
13099 return DB_NO_MEMORY;
13100 }
13101
13102 memset(&_record_list[_record_list_entries], 0, sizeof(RECORD_LIST));
13103
13105 }
13106 }
13107
13108 db_get_key(hDB, hKey, &key);
13109
13110 /* check record size */
13111 status = db_get_record_size(hDB, hKey, 0, &size);
13112 if (status != DB_SUCCESS) {
13114 cm_msg(MERROR, "db_open_record", "cannot get record size, db_get_record_size() status %d", status);
13115 return DB_NO_MEMORY;
13116 }
13117
13118 if (size != rec_size && ptr != NULL) {
13120 std::string path = db_get_path(hDB, hKey);
13121 cm_msg(MERROR, "db_open_record", "struct size mismatch for \"%s\" (expected size: %d, size in ODB: %d)", path.c_str(), rec_size, size);
13123 }
13124
13125 /* check for read access */
13126 if (((key.access_mode & MODE_EXCLUSIVE) && (access_mode & MODE_WRITE))
13127 || (!(key.access_mode & MODE_WRITE) && (access_mode & MODE_WRITE))
13128 || (!(key.access_mode & MODE_READ) && (access_mode & MODE_READ))) {
13130 return DB_NO_ACCESS;
13131 }
13132
13133 if (access_mode & MODE_ALLOC) {
13134 data = malloc(size);
13135
13136 if (data == NULL) {
13138 cm_msg(MERROR, "db_open_record", "not enough memory, malloc(%d) returned NULL", size);
13139 return DB_NO_MEMORY;
13140 }
13141
13142 memset(data, 0, size);
13143
13144 *((void **) ptr) = data;
13145 } else {
13146 data = ptr;
13147 }
13148
13149 /* copy record to local memory */
13150 if (access_mode & MODE_READ && data != NULL) {
13151 status = db_get_record(hDB, hKey, data, &size, 0);
13152 if (status != DB_SUCCESS) {
13154 cm_msg(MERROR, "db_open_record", "cannot get record, db_get_record() status %d", status);
13155 return DB_NO_MEMORY;
13156 }
13157 }
13158
13159 /* copy local record to ODB */
13160 if (access_mode & MODE_WRITE) {
13161 /* only write to ODB if not in MODE_ALLOC */
13162 if ((access_mode & MODE_ALLOC) == 0) {
13163 status = db_set_record(hDB, hKey, data, size, 0);
13164 if (status != DB_SUCCESS) {
13166 cm_msg(MERROR, "db_open_record", "cannot set record, db_set_record() status %d", status);
13167 return DB_NO_MEMORY;
13168 }
13169 }
13170
13171 /* init a local copy of the record */
13172 _record_list[idx].copy = malloc(size);
13173 if (_record_list[idx].copy == NULL) {
13174 cm_msg(MERROR, "db_open_record", "not enough memory");
13175 return DB_NO_MEMORY;
13176 }
13177
13178 memcpy(_record_list[idx].copy, data, size);
13179 }
13180
13181 /* initialize record list */
13182 _record_list[idx].handle = hKey;
13183 _record_list[idx].hDB = hDB;
13184 _record_list[idx].access_mode = access_mode;
13185 _record_list[idx].data = data;
13186 _record_list[idx].buf_size = size;
13187 _record_list[idx].dispatcher = dispatcher;
13188 _record_list[idx].info = info;
13189
13190 /* add record entry in database structure */
13191 return db_add_open_record(hDB, hKey, (WORD) (access_mode & ~MODE_ALLOC));
13192}
INT db_set_record(HNDLE hDB, HNDLE hKey, void *data, INT buf_size, INT align)
Definition odb.cxx:12067
INT db_add_open_record(HNDLE hDB, HNDLE hKey, WORD access_mode)
Definition odb.cxx:12140
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 13220 of file odb.cxx.

13223{
13224 if (rec_str) {
13225 int status;
13226 if (rec_size) {
13227 char* pbuf;
13228 int size = rec_size;
13229 pbuf = (char*)malloc(size);
13230 assert(pbuf != NULL);
13231 status = db_get_record1(hDB, hKey, pbuf, &size, 0, rec_str);
13232 free(pbuf);
13233 if (status != DB_SUCCESS)
13234 return status;
13235 }
13236
13237 status = db_check_record(hDB, hKey, "", rec_str, TRUE);
13238 if (status != DB_SUCCESS)
13239 return status;
13240 }
13241
13242 return db_open_record(hDB, hKey, ptr, rec_size, access_mode, dispatcher, info);
13243}
INT db_get_record1(HNDLE hDB, HNDLE hKey, void *data, INT *buf_size, INT align, const char *rec_str)
Definition odb.cxx:11581
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 11642 of file odb.cxx.

11643{
11644 title[0] = 0;
11645 key_name[0] = 0;
11646 *tid = 0;
11647 *n_data = 0;
11648 *string_length = 0;
11649 *out_rec_str = NULL;
11650
11651 //
11652 // expected format of rec_str:
11653 //
11654 // title: "[.]",
11655 // numeric value: "example_int = INT : 3",
11656 // string value: "example_string = STRING : [20] /Runinfo/Run number",
11657 // array: "aaa = INT[10] : ...",
11658 // string array: "sarr = STRING[10] : [32] ",
11659 //
11660
11661 //printf("parse_rec_str: [%s]\n", rec_str);
11662
11663 while (*rec_str == '\n')
11664 rec_str++;
11665
11666 /* check if it is a section title */
11667 if (rec_str[0] == '[') {
11668 rec_str++;
11669
11670 title[0] = 0;
11671
11672 /* extract title and append '/' */
11673 mstrlcpy(title, rec_str, title_size);
11674 char* p = strchr(title, ']');
11675 if (p)
11676 *p = 0;
11677
11678 int len = strlen(title);
11679 if (len > 0) {
11680 if (title[len - 1] != '/')
11681 mstrlcat(title, "/", title_size);
11682 }
11683
11684 // skip to the next end-of-line
11685 const char* pend = strchr(rec_str, '\n');
11686 if (pend)
11687 rec_str = pend;
11688 else
11689 rec_str = rec_str+strlen(rec_str);
11690
11691 while (*rec_str == '\n')
11692 rec_str++;
11693
11694 *out_rec_str = rec_str;
11695 return DB_SUCCESS;
11696 }
11697
11698 if (rec_str[0] == ';') {
11699 // skip to the next end-of-line
11700 const char* pend = strchr(rec_str, '\n');
11701 if (pend)
11702 rec_str = pend;
11703 else
11704 rec_str = rec_str+strlen(rec_str);
11705
11706 while (*rec_str == '\n')
11707 rec_str++;
11708
11709 *out_rec_str = rec_str;
11710 return DB_SUCCESS;
11711 }
11712
11713 const char* peq = strchr(rec_str, '=');
11714 if (!peq) {
11715 cm_msg(MERROR, "db_parse_record", "do not see \'=\'");
11716 return DB_INVALID_PARAM;
11717 }
11718
11719 int key_name_len = peq - rec_str;
11720
11721 // remove trailing equals sign and trailing spaces
11722 while (key_name_len > 1) {
11723 if (rec_str[key_name_len-1] == '=') {
11724 key_name_len--;
11725 continue;
11726 }
11727 if (rec_str[key_name_len-1] == ' ') {
11728 key_name_len--;
11729 continue;
11730 }
11731 break;
11732 }
11733
11734 memcpy(key_name, rec_str, key_name_len);
11735 key_name[key_name_len] = 0;
11736
11737 rec_str = peq + 1; // consume the "=" sign
11738
11739 while (*rec_str == ' ') // consume spaces
11740 rec_str++;
11741
11742 // extract type id
11743 char stid[256];
11744 int i;
11745 for (i=0; i<(int)sizeof(stid)-1; i++) {
11746 char s = *rec_str;
11747 if (s == 0) break;
11748 if (s == ' ') break;
11749 if (s == '\n') break;
11750 if (s == '[') break;
11751 stid[i] = s;
11752 rec_str++;
11753 }
11754 stid[i] = 0;
11755
11756 DWORD xtid = 0;
11757 for (xtid = 0; xtid < TID_LAST; xtid++) {
11758 if (strcmp(rpc_tid_name(xtid), stid) == 0) {
11759 *tid = xtid;
11760 break;
11761 }
11762 }
11763
11764 //printf("tid [%s], tid %d\n", stid, *tid);
11765
11766 if (xtid == TID_LAST) {
11767 cm_msg(MERROR, "db_parse_record", "do not see \':\'");
11768 return DB_INVALID_PARAM;
11769 }
11770
11771 while (*rec_str == ' ') // consume spaces
11772 rec_str++;
11773
11774 *n_data = 1;
11775
11776 if (*rec_str == '[') {
11777 // decode array size
11778 rec_str++; // cosume the '['
11779 *n_data = atoi(rec_str);
11780 const char *pbr = strchr(rec_str, ']');
11781 if (!pbr) {
11782 cm_msg(MERROR, "db_parse_record", "do not see closing bracket \']\'");
11783 return DB_INVALID_PARAM;
11784 }
11785 rec_str = pbr + 1; // skip the closing bracket
11786 }
11787
11788 while (*rec_str == ' ') // consume spaces
11789 rec_str++;
11790
11791 const char* pcol = strchr(rec_str, ':');
11792 if (!pcol) {
11793 cm_msg(MERROR, "db_parse_record", "do not see \':\'");
11794 return DB_INVALID_PARAM;
11795 }
11796
11797 rec_str = pcol + 1; // skip the ":"
11798
11799 while (*rec_str == ' ') // consume spaces
11800 rec_str++;
11801
11802 *string_length = 0;
11803 if (xtid == TID_LINK || xtid == TID_STRING) {
11804 // extract string length
11805 const char* pbr = strchr(rec_str, '[');
11806 if (pbr) {
11807 *string_length = atoi(pbr+1);
11808 }
11809 }
11810
11811 // skip to the next end-of-line
11812 const char* pend = strchr(rec_str, '\n');
11813 if (pend)
11814 rec_str = pend;
11815 else
11816 rec_str = rec_str+strlen(rec_str);
11817
11818 while (*rec_str == '\n')
11819 rec_str++;
11820
11821 *out_rec_str = rec_str;
11822 return DB_SUCCESS;
11823}
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 8252 of file odb.cxx.

8253{
8254 char title[MAX_STRING_LENGTH];
8255 char *data;
8256 const char *pold;
8257 INT data_size, index;
8258 INT tid, i, j, n_data, string_length, status, size;
8259 HNDLE hKey;
8260 KEY root_key;
8261
8262 title[0] = 0;
8263
8264 if (hKeyRoot == 0)
8265 db_find_key(hDB, hKeyRoot, "", &hKeyRoot);
8266
8267 db_get_key(hDB, hKeyRoot, &root_key);
8268
8269 /* initial data size */
8270 data_size = 1000;
8271 data = (char *) malloc(data_size);
8272 if (data == NULL) {
8273 cm_msg(MERROR, "db_paste", "cannot allocate data buffer");
8274 return DB_NO_MEMORY;
8275 }
8276
8277 do {
8278 char line[10*MAX_STRING_LENGTH];
8279
8280 if (*buffer == 0)
8281 break;
8282
8283 for (i = 0; *buffer != '\n' && *buffer && i < 10*MAX_STRING_LENGTH; i++)
8284 line[i] = *buffer++;
8285
8286 if (i == 10*MAX_STRING_LENGTH) {
8287 line[10*MAX_STRING_LENGTH-1] = 0;
8288 cm_msg(MERROR, "db_paste", "line too long: %s...", line);
8289 free(data);
8290 return DB_TRUNCATED;
8291 }
8292
8293 line[i] = 0;
8294 if (*buffer == '\n')
8295 buffer++;
8296
8297 /* check if it is a section title */
8298 if (line[0] == '[') {
8299 /* extract title and append '/' */
8300 mstrlcpy(title, line + 1, sizeof(title));
8301 if (strchr(title, ']'))
8302 *strchr(title, ']') = 0;
8303 if (title[0] && title[strlen(title) - 1] != '/')
8304 mstrlcat(title, "/", sizeof(title));
8305 } else {
8306 /* valid data line if it includes '=' and no ';' */
8307 if (strchr(line, '=') && line[0] != ';') {
8308 char key_name[MAX_ODB_PATH];
8309 char test_str[MAX_ODB_PATH];
8310 char data_str[10*MAX_STRING_LENGTH];
8311
8312 /* copy type info and data */
8313 char* pline = strrchr(line, '=') + 1;
8314 while (strstr(line, ": [") != NULL && strstr(line, ": [") < pline) {
8315 pline -= 2;
8316 while (*pline != '=' && pline > line)
8317 pline--;
8318 pline++;
8319 }
8320 while (*pline == ' ')
8321 pline++;
8322 mstrlcpy(data_str, pline, sizeof(data_str));
8323
8324 /* extract key name */
8325 *strrchr(line, '=') = 0;
8326 while (strstr(line, ": [") && strchr(line, '='))
8327 *strrchr(line, '=') = 0;
8328
8329 pline = &line[strlen(line) - 1];
8330 while (*pline == ' ')
8331 *pline-- = 0;
8332
8333 key_name[0] = 0;
8334 if (title[0] != '.')
8335 mstrlcpy(key_name, title, sizeof(key_name));
8336
8337 mstrlcat(key_name, line, sizeof(key_name));
8338
8339 /* evaluate type info */
8340 mstrlcpy(line, data_str, sizeof(line));
8341 if (strchr(line, ' '))
8342 *strchr(line, ' ') = 0;
8343
8344 n_data = 1;
8345 if (strchr(line, '[')) {
8346 n_data = atol(strchr(line, '[') + 1);
8347 *strchr(line, '[') = 0;
8348 }
8349
8350 for (tid = 0; tid < TID_LAST; tid++)
8351 if (strcmp(rpc_tid_name(tid), line) == 0)
8352 break;
8353 if (tid == TID_LAST) {
8354 for (tid = 0; tid < TID_LAST; tid++)
8355 if (strcmp(rpc_tid_name_old(tid), line) == 0)
8356 break;
8357 }
8358
8359 string_length = 0;
8360
8361 if (tid == TID_LAST)
8362 cm_msg(MERROR, "db_paste", "found unknown data type \"%s\" in ODB file", line);
8363 else {
8364 /* skip type info */
8365 char* pc = data_str;
8366 while (*pc != ' ' && *pc)
8367 pc++;
8368 while ((*pc == ' ' || *pc == ':') && *pc)
8369 pc++;
8370
8371 //mstrlcpy(data_str, pc, sizeof(data_str)); // MacOS 10.9 does not permit mstrlcpy() of overlapping strings
8372 assert(strlen(pc) < sizeof(data_str)); // "pc" points at a substring inside "data_str"
8373 memmove(data_str, pc, strlen(pc)+1);
8374
8375 if (n_data > 1) {
8376 data_str[0] = 0;
8377 if (!*buffer)
8378 break;
8379
8380 for (j = 0; *buffer != '\n' && *buffer; j++)
8381 data_str[j] = *buffer++;
8382 data_str[j] = 0;
8383 if (*buffer == '\n')
8384 buffer++;
8385 }
8386
8387 for (i = 0; i < n_data; i++) {
8388 /* strip trailing \n */
8389 char* pc = &data_str[strlen(data_str) - 1];
8390 while (*pc == '\n' || *pc == '\r')
8391 *pc-- = 0;
8392
8393 if (tid == TID_STRING || tid == TID_LINK) {
8394 if (!string_length) {
8395 if (data_str[1] == '=')
8396 string_length = -1;
8397 else
8398 string_length = atoi(data_str + 1);
8399 if (string_length > MAX_STRING_LENGTH) {
8400 string_length = MAX_STRING_LENGTH;
8401 cm_msg(MERROR, "db_paste", "found string exceeding MAX_STRING_LENGTH, odb path \"%s\"", key_name);
8402 }
8403 if (string_length == 0) {
8404 string_length = 32;
8405 cm_msg(MERROR, "db_paste", "found string length of zero, set to 32, odb path \"%s\"", key_name);
8406 }
8407 }
8408
8409 if (string_length == -1) {
8410 /* multi-line string */
8411 if (strstr(buffer, "\n====#$@$#====\n") != NULL) {
8412 string_length = (POINTER_T) strstr(buffer, "\n====#$@$#====\n") - (POINTER_T) buffer + 1;
8413
8414 if (string_length >= data_size) {
8415 data_size += string_length + 100;
8416 data = (char *) realloc(data, data_size);
8417 if (data == NULL) {
8418 cm_msg(MERROR, "db_paste", "cannot allocate data buffer");
8419 return DB_NO_MEMORY;
8420 }
8421 }
8422
8423 memset(data, 0, data_size);
8424 strncpy(data, buffer, string_length);
8425 data[string_length - 1] = 0;
8426 buffer = strstr(buffer, "\n====#$@$#====\n") + strlen("\n====#$@$#====\n");
8427 } else
8428 cm_msg(MERROR, "db_paste", "found multi-line string without termination sequence");
8429 } else {
8430 char* pc = data_str + 2;
8431 while (*pc && *pc != ' ')
8432 pc++;
8433
8434 // skip one space (needed for strings starting with spaces)
8435 if (*pc)
8436 pc++;
8437
8438 /* limit string size */
8439 *(pc + string_length - 1) = 0;
8440
8441 /* increase data buffer if necessary */
8442 if (string_length * (i + 1) >= data_size) {
8443 data_size += 1000;
8444 data = (char *) realloc(data, data_size);
8445 if (data == NULL) {
8446 cm_msg(MERROR, "db_paste", "cannot allocate data buffer");
8447 return DB_NO_MEMORY;
8448 }
8449 }
8450
8451 mstrlcpy(data + string_length * i, pc, string_length);
8452 }
8453 } else {
8454 char* pc = data_str;
8455
8456 if (n_data > 1 && data_str[0] == '[') {
8457 index = atoi(data_str+1);
8458 pc = strchr(data_str, ']') + 1;
8459 while (*pc && *pc == ' ')
8460 pc++;
8461 } else
8462 index = 0;
8463
8464 /* increase data buffer if necessary */
8465 if (rpc_tid_size(tid) * (index + 1) >= data_size) {
8466 data_size += 1000;
8467 data = (char *) realloc(data, data_size);
8468 if (data == NULL) {
8469 cm_msg(MERROR, "db_paste", "cannot allocate data buffer");
8470 return DB_NO_MEMORY;
8471 }
8472 }
8473
8474 db_sscanf(pc, data, &size, index, tid);
8475 }
8476
8477 if (i < n_data - 1) {
8478 data_str[0] = 0;
8479 if (!*buffer)
8480 break;
8481
8482 pold = buffer;
8483
8484 for (j = 0; *buffer != '\n' && *buffer; j++)
8485 data_str[j] = *buffer++;
8486 data_str[j] = 0;
8487 if (*buffer == '\n')
8488 buffer++;
8489
8490 /* test if valid data */
8491 if (tid != TID_STRING && tid != TID_LINK) {
8492 if (data_str[0] == 0 || (strchr(data_str, '=')
8493 && strchr(data_str, ':')))
8494 buffer = pold;
8495 }
8496 }
8497 }
8498
8499 /* skip system client entries */
8500 mstrlcpy(test_str, key_name, sizeof(test_str));
8501 test_str[15] = 0;
8502
8503 if (!equal_ustring(test_str, "/System/Clients")) {
8504 if (root_key.type != TID_KEY) {
8505 /* root key is destination key */
8506 hKey = hKeyRoot;
8507 } else {
8508 /* create key and set value */
8509 if (key_name[0] == '/') {
8510 status = db_find_link(hDB, 0, key_name, &hKey);
8511 if (status == DB_NO_KEY) {
8512 db_create_key(hDB, 0, key_name, tid);
8513 status = db_find_link(hDB, 0, key_name, &hKey);
8514 }
8515 } else {
8516 status = db_find_link(hDB, hKeyRoot, key_name, &hKey);
8517 if (status == DB_NO_KEY) {
8518 db_create_key(hDB, hKeyRoot, key_name, tid);
8519 status = db_find_link(hDB, hKeyRoot, key_name, &hKey);
8520 }
8521 }
8522 }
8523
8524 /* set key data if created successfully */
8525 if (hKey) {
8526 if (tid == TID_STRING || tid == TID_LINK)
8527 db_set_link_data(hDB, hKey, data, string_length * n_data, n_data, tid);
8528 else
8529 db_set_link_data(hDB, hKey, data, rpc_tid_size(tid) * n_data, n_data, tid);
8530 }
8531 }
8532 }
8533 }
8534 }
8535 } while (TRUE);
8536
8537 free(data);
8538 return DB_SUCCESS;
8539}
INT db_sscanf(const char *data_str, void *data, INT *data_size, INT i, DWORD tid)
Definition odb.cxx:11083
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 8545 of file odb.cxx.

8546{
8547 int status;
8548
8549 if (strcmp(mxml_get_name(node), "odb") == 0) {
8550 for (int i = 0; i < mxml_get_number_of_children(node); i++) {
8551 status = db_paste_node(hDB, hKeyRoot, mxml_subnode(node, i));
8552 if (status != DB_SUCCESS)
8553 return status;
8554 }
8555 } else if (strcmp(mxml_get_name(node), "dir") == 0) {
8556 const char* name = mxml_get_attribute(node, "name");
8557
8558 if (name == NULL) {
8559 cm_msg(MERROR, "db_paste_node", "found key \"%s\" with no name in XML data", mxml_get_name(node));
8560 return DB_TYPE_MISMATCH;
8561 }
8562
8563 HNDLE hKey;
8564 status = db_find_link(hDB, hKeyRoot, name, &hKey);
8565
8566 if (status == DB_NO_KEY) {
8567 status = db_create_key(hDB, hKeyRoot, name, TID_KEY);
8568 if (status == DB_NO_ACCESS) {
8569 cm_msg(MINFO, "db_paste_node", "cannot load key \"%s\": write protected", name);
8570 return DB_SUCCESS; /* key or tree is locked, just skip it */
8571 }
8572
8573 if (status != DB_SUCCESS && status != DB_KEY_EXIST) {
8574 cm_msg(MERROR, "db_paste_node", "cannot create key \"%s\" in ODB, status = %d", name, status);
8575 return status;
8576 }
8577 status = db_find_link(hDB, hKeyRoot, name, &hKey);
8578 if (status != DB_SUCCESS) {
8579 cm_msg(MERROR, "db_paste_node", "cannot find key \"%s\" in ODB", name);
8580 return status;
8581 }
8582 }
8583
8584 std::string path = db_get_path(hDB, hKey);
8585 if (!equal_ustring(path.c_str(), "/System/Clients")) {
8586 for (int i = 0; i < mxml_get_number_of_children(node); i++) {
8587 status = db_paste_node(hDB, hKey, mxml_subnode(node, i));
8588 if (status != DB_SUCCESS)
8589 return status;
8590 }
8591 }
8592 } else if (strcmp(mxml_get_name(node), "key") == 0 || strcmp(mxml_get_name(node), "keyarray") == 0) {
8593
8594 const char* name = mxml_get_attribute(node, "name");
8595
8596 if (name == NULL) {
8597 cm_msg(MERROR, "db_paste_node", "found key \"%s\" with no name in XML data", mxml_get_name(node));
8598 return DB_TYPE_MISMATCH;
8599 }
8600
8601 int num_values;
8602 if (strcmp(mxml_get_name(node), "keyarray") == 0)
8603 num_values = atoi(mxml_get_attribute(node, "num_values"));
8604 else
8605 num_values = 0;
8606
8607 const char* type = mxml_get_attribute(node, "type");
8608
8609 if (type == NULL) {
8610 cm_msg(MERROR, "db_paste_node", "found key \"%s\" with no type in XML data", mxml_get_name(node));
8611 return DB_TYPE_MISMATCH;
8612 }
8613
8614 int tid = rpc_name_tid(type);
8615 if (tid == 0) {
8616 cm_msg(MERROR, "db_paste_node", "found unknown data type \"%s\" in XML data", type);
8617 return DB_TYPE_MISMATCH;
8618 }
8619
8620 HNDLE hKey;
8621 status = db_find_link(hDB, hKeyRoot, name, &hKey);
8622 if (status == DB_NO_KEY) {
8623 status = db_create_key(hDB, hKeyRoot, name, tid);
8624 if (status == DB_NO_ACCESS) {
8625 cm_msg(MINFO, "db_paste_node", "cannot load key \"%s\": write protected", name);
8626 return DB_SUCCESS; /* key or tree is locked, just skip it */
8627 }
8628
8629 if (status != DB_SUCCESS) {
8630 cm_msg(MERROR, "db_paste_node", "cannot create key \"%s\" in ODB, status = %d", name, status);
8631 return status;
8632 }
8633 status = db_find_link(hDB, hKeyRoot, name, &hKey);
8634 if (status != DB_SUCCESS) {
8635 cm_msg(MERROR, "db_paste_node", "cannot find key \"%s\" in ODB, status = %d", name, status);
8636 return status;
8637 }
8638 } else {
8639 KEY key;
8641 if (status != DB_SUCCESS) {
8642 cm_msg(MERROR, "db_paste_node", "cannot get key \"%s\" in ODB, status = %d", name, status);
8643 return status;
8644 }
8645
8646 if (num_values > 0 && num_values != key.num_values && key.item_size > 0) {
8647 status = db_set_num_values(hDB, hKey, num_values);
8648 if (status != DB_SUCCESS) {
8649 cm_msg(MERROR, "db_paste_node", "cannot resize key \"%s\" in ODB, status = %d", name, status);
8650 return status;
8651 }
8652 }
8653 }
8654
8655 int size = 0;
8656 char *buf = NULL;
8657
8658 if (tid == TID_STRING || tid == TID_LINK) {
8659 size = atoi(mxml_get_attribute(node, "size"));
8660 buf = (char *)malloc(size);
8661 assert(buf);
8662 buf[0] = 0;
8663 }
8664
8665 if (num_values) {
8666 /* evaluate array */
8667 for (int i = 0; i < mxml_get_number_of_children(node); i++) {
8668 PMXML_NODE child = mxml_subnode(node, i);
8669 int idx;
8670 if (mxml_get_attribute(child, "index"))
8671 idx = atoi(mxml_get_attribute(child, "index"));
8672 else
8673 idx = i;
8674 if (tid == TID_STRING || tid == TID_LINK) {
8675 if (mxml_get_value(child) == NULL) {
8676 status = db_set_data_index(hDB, hKey, "", size, i, tid);
8677 if (status == DB_NO_ACCESS) {
8678 cm_msg(MINFO, "db_paste_node", "cannot load string or link \"%s\": write protected", mxml_get_attribute(node, "name"));
8679 return DB_SUCCESS; /* key or tree is locked, just skip it */
8680 } else if (status != DB_SUCCESS) {
8681 cm_msg(MERROR, "db_paste_node", "cannot load string or link \"%s\": db_set_data_index() status %d", mxml_get_attribute(node, "name"), status);
8682 return status;
8683 }
8684 } else {
8685 mstrlcpy(buf, mxml_get_value(child), size);
8686 status = db_set_data_index(hDB, hKey, buf, size, idx, tid);
8687 if (status == DB_NO_ACCESS) {
8688 cm_msg(MINFO, "db_paste_node", "cannot load array element \"%s\": write protected", mxml_get_attribute(node, "name"));
8689 return DB_SUCCESS; /* key or tree is locked, just skip it */
8690 } else if (status != DB_SUCCESS) {
8691 cm_msg(MERROR, "db_paste_node", "cannot load array element \"%s\": db_set_data_index() status %d", mxml_get_attribute(node, "name"), status);
8692 return status;
8693 }
8694 }
8695 } else {
8696 char data[256];
8697 db_sscanf(mxml_get_value(child), data, &size, 0, tid);
8698 status = db_set_data_index(hDB, hKey, data, rpc_tid_size(tid), idx, tid);
8699 if (status == DB_NO_ACCESS) {
8700 cm_msg(MINFO, "db_paste_node", "cannot load array element \"%s\": write protected", mxml_get_attribute(node, "name"));
8701 return DB_SUCCESS; /* key or tree is locked, just skip it */
8702 } else if (status != DB_SUCCESS) {
8703 cm_msg(MERROR, "db_paste_node", "cannot load array element \"%s\": db_set_data_index() status %d", mxml_get_attribute(node, "name"), status);
8704 return status;
8705 }
8706 }
8707 }
8708
8709 } else { /* single value */
8710 if (tid == TID_STRING || tid == TID_LINK) {
8711 size = atoi(mxml_get_attribute(node, "size"));
8712 if (mxml_get_value(node) == NULL) {
8713 status = db_set_data(hDB, hKey, "", size, 1, tid);
8714 if (status == DB_NO_ACCESS) {
8715 cm_msg(MINFO, "db_paste_node", "cannot load string or link \"%s\": write protected", mxml_get_attribute(node, "name"));
8716 return DB_SUCCESS; /* key or tree is locked, just skip it */
8717 } else if (status != DB_SUCCESS) {
8718 cm_msg(MERROR, "db_paste_node", "cannot load string or link \"%s\": db_set_data() status %d", mxml_get_attribute(node, "name"), status);
8719 return status;
8720 }
8721 } else {
8722 mstrlcpy(buf, mxml_get_value(node), size);
8723 status = db_set_data(hDB, hKey, buf, size, 1, tid);
8724 if (status == DB_NO_ACCESS) {
8725 cm_msg(MINFO, "db_paste_node", "cannot load value \"%s\": write protected", mxml_get_attribute(node, "name"));
8726 return DB_SUCCESS; /* key or tree is locked, just skip it */
8727 } else if (status != DB_SUCCESS) {
8728 cm_msg(MERROR, "db_paste_node", "cannot load value \"%s\": db_set_data() status %d", mxml_get_attribute(node, "name"), status);
8729 return status;
8730 }
8731 }
8732 } else {
8733 char data[256];
8734 db_sscanf(mxml_get_value(node), data, &size, 0, tid);
8735 status = db_set_data(hDB, hKey, data, rpc_tid_size(tid), 1, tid);
8736 if (status == DB_NO_ACCESS) {
8737 cm_msg(MINFO, "db_paste_node", "cannot load value \"%s\": write protected", mxml_get_attribute(node, "name"));
8738 return DB_SUCCESS; /* key or tree is locked, just skip it */
8739 } else if (status != DB_SUCCESS) {
8740 cm_msg(MERROR, "db_paste_node", "cannot load value \"%s\": db_set_data() status %d", mxml_get_attribute(node, "name"), status);
8741 return status;
8742 }
8743 }
8744 }
8745
8746 if (buf) {
8747 free(buf);
8748 buf = NULL;
8749 }
8750 }
8751
8752 return DB_SUCCESS;
8753}
static int db_paste_node(HNDLE hDB, HNDLE hKeyRoot, PMXML_NODE node)
Definition odb.cxx:8545
INT db_set_num_values(HNDLE hDB, HNDLE hKey, INT num_values)
Definition odb.cxx:7270
int rpc_name_tid(const char *name)
Definition midas.cxx:11803
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 8763 of file odb.cxx.

8764{
8765 char error[256];
8766 INT status;
8767 PMXML_NODE tree, node;
8768
8769 if (hKeyRoot == 0)
8770 db_find_key(hDB, hKeyRoot, "", &hKeyRoot);
8771
8772 /* parse XML buffer */
8773 tree = mxml_parse_buffer(buffer, error, sizeof(error), NULL);
8774 if (tree == NULL) {
8775 puts(error);
8776 return DB_TYPE_MISMATCH;
8777 }
8778
8779 node = mxml_find_node(tree, "odb");
8780 if (node == NULL) {
8781 puts("Cannot find element \"odb\" in XML data");
8782 return DB_TYPE_MISMATCH;
8783 }
8784
8785 status = db_paste_node(hDB, hKeyRoot, node);
8786
8787 mxml_free_tree(tree);
8788
8789 return status;
8790}
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 11208 of file odb.cxx.

11217{
11218 const KEY *pold;
11219 INT size, align, corr, total_size_tmp;
11220
11221 const DATABASE_HEADER* pheader = pdb->database_header;
11222
11223 const KEYLIST *pkeylist = (const KEYLIST *) ((const char *) pheader + pkey->data);
11224 if (!pkeylist->first_key)
11225 return;
11226
11227 // FIXME: validate pkeylist->first_key
11228 // FIXME: confusing reuse of pkey
11229 pkey = (const KEY *) ((char *) pheader + pkeylist->first_key);
11230
11231 /* first browse through this level */
11232 do {
11233 pold = NULL;
11234
11235 if (pkey->type == TID_LINK) {
11236 const KEY *plink = db_resolve_link_locked(pheader, pkey, NULL, msg);
11237
11238 if (!plink)
11239 return;
11240
11241 if (plink->type == TID_KEY) {
11242 db_recurse_record_tree_locked(pdb, plink, data, total_size, base_align, NULL, bSet, convert_flags, msg);
11243 } else {
11244 pold = pkey;
11245 pkey = plink;
11246 }
11247 }
11248
11249 if (pkey->type != TID_KEY) {
11250 /* correct for alignment */
11251 align = 1;
11252
11253 if (rpc_tid_size(pkey->type))
11254 align = rpc_tid_size(pkey->type) < base_align ? rpc_tid_size(pkey->type) : base_align;
11255
11256 if (max_align && align > *max_align)
11257 *max_align = align;
11258
11259 corr = VALIGN(*total_size, align) - *total_size;
11260 *total_size += corr;
11261 if (data)
11262 *data = (void *) ((char *) (*data) + corr);
11263
11264 /* calculate data size */
11265 size = pkey->item_size * pkey->num_values;
11266
11267 if (data) {
11268 if (bSet) {
11269 KEY* wpkey = (KEY*)pkey;
11270 /* copy data if there is write access */
11271 if (pkey->access_mode & MODE_WRITE) {
11272 memcpy((char *) pheader + pkey->data, *data, pkey->item_size * pkey->num_values);
11273
11274 /* convert data */
11275 if (convert_flags) {
11276 if (pkey->num_values > 1)
11277 rpc_convert_data((char *) pheader + pkey->data,
11278 pkey->type, RPC_FIXARRAY, pkey->item_size * pkey->num_values, convert_flags);
11279 else
11280 rpc_convert_single((char *) pheader + pkey->data, pkey->type, 0, convert_flags);
11281 }
11282
11283 /* update time */
11284 wpkey->last_written = ss_time();
11285
11286 /* notify clients which have key open */
11287 db_notify_clients_locked(pdb, db_pkey_to_hkey(pheader, pkey), -1, TRUE, msg);
11288 }
11289 } else {
11290 /* copy key data if there is read access */
11291 if (pkey->access_mode & MODE_READ) {
11292 memcpy(*data, (char *) pheader + pkey->data, pkey->item_size * pkey->num_values);
11293
11294 /* convert data */
11295 if (convert_flags) {
11296 if (pkey->num_values > 1)
11297 rpc_convert_data(*data, pkey->type,
11299 pkey->item_size * pkey->num_values, convert_flags);
11300 else
11301 rpc_convert_single(*data, pkey->type, RPC_OUTGOING, convert_flags);
11302 }
11303 }
11304 }
11305
11306 *data = (char *) (*data) + size;
11307 }
11308
11309 *total_size += size;
11310 } else {
11311 /* align new substructure according to the maximum
11312 align value in this structure */
11313 align = 1;
11314
11315 total_size_tmp = *total_size;
11316 db_recurse_record_tree_locked(pdb, pkey, NULL, &total_size_tmp, base_align, &align, bSet, convert_flags, msg);
11317
11318 if (max_align && align > *max_align)
11319 *max_align = align;
11320
11321 corr = VALIGN(*total_size, align) - *total_size;
11322 *total_size += corr;
11323 if (data)
11324 *data = (void *) ((char *) (*data) + corr);
11325
11326 /* now recurse subtree */
11327 db_recurse_record_tree_locked(pdb, pkey, data, total_size, base_align, NULL, bSet, convert_flags, msg);
11328
11329 corr = VALIGN(*total_size, align) - *total_size;
11330 *total_size += corr;
11331 if (data)
11332 *data = (void *) ((char *) (*data) + corr);
11333 }
11334
11335 if (pold) {
11336 pkey = pold;
11337 pold = NULL;
11338 }
11339
11340 if (!pkey->next_key)
11341 break;
11342
11343 // FIXME: validate pkey->next_key
11344 pkey = (KEY *) ((char *) pheader + pkey->next_key);
11345 } while (TRUE);
11346}
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 11348 of file odb.cxx.

11357{
11358 /* get first subkey of hKey */
11359
11360 const KEY* pkey = db_get_pkey(pdb->database_header, hKey, NULL, "db_recurse_record_tree", msg);
11361
11362 if (!pkey) {
11363 return;
11364 }
11365
11366 db_recurse_record_tree_locked(pdb, pkey, data, total_size, base_align, max_align, bSet, convert_flags, msg);
11367}
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 12275 of file odb.cxx.

12283{
12284 if (rpc_is_remote())
12286
12287 int status = DB_SUCCESS;
12288
12289#ifdef LOCAL_ROUTINES
12290 {
12291 if (hDB > _database_entries || hDB <= 0) {
12292 cm_msg(MERROR, "db_remove_open_record", "invalid database handle %d", hDB);
12293 return DB_INVALID_HANDLE;
12294 }
12295
12297
12298 DATABASE *pdb = &_database[hDB - 1];
12299 DATABASE_HEADER *pheader = pdb->database_header;
12300
12301 db_allow_write_locked(pdb, "db_remove_open_record");
12302
12303 status = db_remove_open_record_wlocked(pdb, pheader, hKey);
12304
12306 }
12307#endif /* LOCAL_ROUTINES */
12308
12309 return status;
12310}
#define RPC_DB_REMOVE_OPEN_RECORD
Definition mrpc.h:73
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_remove_open_record_wlocked()

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

Definition at line 12229 of file odb.cxx.

12230{
12231 int status = DB_SUCCESS;
12232
12234
12235 /* search key */
12236 int idx;
12237 for (idx = 0; idx < pclient->max_index; idx++)
12238 if (pclient->open_record[idx].handle == hKey)
12239 break;
12240
12241 if (idx == pclient->max_index) {
12242 return DB_INVALID_HANDLE;
12243 }
12244
12245 KEY* pkey = (KEY*)db_get_pkey(pheader, hKey, &status, "db_remove_open_record_wlocked", NULL);
12246
12247 if (!pkey)
12248 return status;
12249
12250 /* decrement notify_count */
12251
12252 if (pkey->notify_count > 0)
12253 pkey->notify_count--;
12254
12255 pclient->num_open_records--;
12256
12257 /* remove exclusive flag */
12258 if (pclient->open_record[idx].access_mode & MODE_WRITE)
12259 db_set_mode_wlocked(pheader, pkey, (WORD) (pkey->access_mode & ~MODE_EXCLUSIVE), 2, NULL);
12260
12261 memset(&pclient->open_record[idx], 0, sizeof(OPEN_RECORD));
12262
12263 /* calculate new max_index entry */
12264 int i;
12265 for (i = pclient->max_index - 1; i >= 0; i--)
12266 if (pclient->open_record[i].handle != 0)
12267 break;
12268 pclient->max_index = i + 1;
12269
12270 return DB_SUCCESS;
12271}
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 6032 of file odb.cxx.

6053{
6054 if (rpc_is_remote())
6056
6057#ifdef LOCAL_ROUTINES
6058 {
6059 DATABASE_HEADER *pheader;
6060 KEY *pkey;
6061 int status;
6062
6063 if (hDB > _database_entries || hDB <= 0) {
6064 cm_msg(MERROR, "db_rename_key", "invalid database handle");
6065 return DB_INVALID_HANDLE;
6066 }
6067
6068 if (!_database[hDB - 1].attached) {
6069 cm_msg(MERROR, "db_rename_key", "invalid database handle");
6070 return DB_INVALID_HANDLE;
6071 }
6072
6073 if (hKey < (int) sizeof(DATABASE_HEADER)) {
6074 cm_msg(MERROR, "db_rename_key", "invalid key handle");
6075 return DB_INVALID_HANDLE;
6076 }
6077
6078 db_err_msg* msg = NULL;
6079 status = db_validate_name(name, FALSE, "db_rename_key", &msg);
6080 if (msg)
6081 db_flush_msg(&msg);
6082 if (status != DB_SUCCESS)
6083 return status;
6084
6085 if (name == NULL) {
6086 cm_msg(MERROR, "db_rename_key", "key name is NULL");
6087 return DB_INVALID_NAME;
6088 }
6089
6090 if (strlen(name) < 1) {
6091 cm_msg(MERROR, "db_rename_key", "key name is too short");
6092 return DB_INVALID_NAME;
6093 }
6094
6095 if (strchr(name, '/')) {
6096 cm_msg(MERROR, "db_rename_key", "key name may not contain \"/\"");
6097 return DB_INVALID_NAME;
6098 }
6099
6101
6102 pheader = _database[hDB - 1].database_header;
6103
6104 /* check if hKey argument is correct */
6105 if (!db_validate_hkey(pheader, hKey)) {
6107 return DB_INVALID_HANDLE;
6108 }
6109
6110 pkey = (KEY *) ((char *) pheader + hKey);
6111
6112 if (!pkey->type) {
6113 int pkey_type = pkey->type;
6115 cm_msg(MERROR, "db_rename_key", "hkey %d invalid key type %d", hKey, pkey_type);
6116 return DB_INVALID_HANDLE;
6117 }
6118
6119 db_allow_write_locked(&_database[hDB - 1], "db_rename_key");
6120
6121 mstrlcpy(pkey->name, name, NAME_LENGTH);
6122
6124
6125 }
6126#endif /* LOCAL_ROUTINES */
6127
6128 return DB_SUCCESS;
6129}
#define RPC_DB_RENAME_KEY
Definition mrpc.h:77
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_reorder_key()

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

Definition at line 6132 of file odb.cxx.

6155{
6156 if (rpc_is_remote())
6157 return rpc_call(RPC_DB_REORDER_KEY, hDB, hKey, idx);
6158
6159#ifdef LOCAL_ROUTINES
6160 {
6161 DATABASE_HEADER *pheader;
6162 KEY *pkey, *pnext_key, *pkey_tmp;
6163 KEYLIST *pkeylist;
6164 INT i;
6165
6166 if (hDB > _database_entries || hDB <= 0) {
6167 cm_msg(MERROR, "db_rename_key", "invalid database handle");
6168 return DB_INVALID_HANDLE;
6169 }
6170
6171 if (!_database[hDB - 1].attached) {
6172 cm_msg(MERROR, "db_rename_key", "invalid database handle");
6173 return DB_INVALID_HANDLE;
6174 }
6175
6176 if (hKey < (int) sizeof(DATABASE_HEADER)) {
6177 cm_msg(MERROR, "db_rename_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 if (!pkey->type) {
6194 int pkey_type = pkey->type;
6196 cm_msg(MERROR, "db_reorder_key", "hkey %d invalid key type %d", hKey, pkey_type);
6197 return DB_INVALID_HANDLE;
6198 }
6199
6200 if (!(pkey->access_mode & MODE_WRITE)) {
6202 return DB_NO_ACCESS;
6203 }
6204
6205 /* check if someone has opened key or parent */
6206 do {
6207#ifdef CHECK_OPEN_RECORD
6208 if (pkey->notify_count) {
6210 return DB_OPEN_RECORD;
6211 }
6212#endif
6213 if (pkey->parent_keylist == 0)
6214 break;
6215
6216 pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
6217 // FIXME: validate pkeylist->parent
6218 pkey = (KEY *) ((char *) pheader + pkeylist->parent);
6219 } while (TRUE);
6220
6221 db_allow_write_locked(&_database[hDB - 1], "db_reorder_key");
6222
6223 pkey = (KEY *) ((char *) pheader + hKey); // NB: hKey is already validated
6224 pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
6225
6226 /* first remove key from list */
6227 pnext_key = (KEY *) (POINTER_T) pkey->next_key; // FIXME: what is this pointer cast?
6228
6229 if ((KEY *) ((char *) pheader + pkeylist->first_key) == pkey) {
6230 /* key is first in list */
6231 pkeylist->first_key = (POINTER_T) pnext_key;
6232 } else {
6233 /* find predecessor */
6234 // FIXME: validate pkeylist->first_key
6235 pkey_tmp = (KEY *) ((char *) pheader + pkeylist->first_key);
6236 while ((KEY *) ((char *) pheader + pkey_tmp->next_key) != pkey) {
6237 // FIXME: validate pkey_tmp->next_key
6238 pkey_tmp = (KEY *) ((char *) pheader + pkey_tmp->next_key);
6239 }
6240 pkey_tmp->next_key = (POINTER_T) pnext_key;
6241 }
6242
6243 /* add key to list at proper index */
6244 // FIXME: validate pkeylist->first_key
6245 pkey_tmp = (KEY *) ((char *) pheader + pkeylist->first_key);
6246 if (idx < 0 || idx >= pkeylist->num_keys - 1) {
6247 /* add at bottom */
6248
6249 /* find last key */
6250 for (i = 0; i < pkeylist->num_keys - 2; i++) {
6251 // FIXME: validate pkey_tmp->next_key
6252 pkey_tmp = (KEY *) ((char *) pheader + pkey_tmp->next_key);
6253 }
6254
6255 pkey_tmp->next_key = (POINTER_T) pkey - (POINTER_T) pheader;
6256 pkey->next_key = 0;
6257 } else {
6258 if (idx == 0) {
6259 /* add at top */
6260 pkey->next_key = pkeylist->first_key;
6261 pkeylist->first_key = (POINTER_T) pkey - (POINTER_T) pheader;
6262 } else {
6263 /* add at position index */
6264 for (i = 0; i < idx - 1; i++) {
6265 // FIXME: validate pkey_tmp->next_key
6266 pkey_tmp = (KEY *) ((char *) pheader + pkey_tmp->next_key);
6267 }
6268
6269 pkey->next_key = pkey_tmp->next_key;
6270 pkey_tmp->next_key = (POINTER_T) pkey - (POINTER_T) pheader;
6271 }
6272 }
6273
6275
6276 }
6277#endif /* LOCAL_ROUTINES */
6278
6279 return DB_SUCCESS;
6280}
#define RPC_DB_REORDER_KEY
Definition mrpc.h:79
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_resize_string()

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

Change size of string arrays.

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

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

Definition at line 13805 of file odb.cxx.

13806{
13807 int status;
13808 int hkey;
13809
13810 //printf("db_resize_string: key_name [%s], num_values %d, max_string_length %d\n", key_name, num_values, max_string_length);
13811
13812 int old_num_values = 0;
13813 int old_item_size = 0;
13814 int old_size = 0;
13815 char* old_data = NULL;
13816
13817 if (key_name) {
13818 status = db_find_key(hdb, hKeyRoot, key_name, &hkey);
13819 } else {
13820 hkey = hKeyRoot;
13822 }
13823 if (status == DB_SUCCESS) {
13824 KEY key;
13825 status = db_get_key(hdb, hkey, &key);
13826 if (status != DB_SUCCESS)
13827 return status;
13828 old_num_values = key.num_values;
13829 old_item_size = key.item_size;
13830 old_size = old_num_values * old_item_size;
13831 if (old_size > 0) {
13832 old_data = (char*)malloc(old_size);
13833 assert(old_data != NULL);
13834 int size = old_size;
13835 status = db_get_data(hdb, hkey, old_data, &size, TID_STRING);
13836 if (status != DB_SUCCESS) {
13837 free(old_data);
13838 return status;
13839 }
13840 assert(size == old_size);
13841 }
13842 } else {
13843 status = db_create_key(hdb, hKeyRoot, key_name, TID_STRING);
13844 if (status != DB_SUCCESS)
13845 return status;
13846 status = db_find_key(hdb, hKeyRoot, key_name, &hkey);
13847 if (status != DB_SUCCESS)
13848 return status;
13849 }
13850
13851 //printf("old_num_values %d, old_item_size %d, old_size %d\n", old_num_values, old_item_size, old_size);
13852
13853 int item_size = max_string_length;
13854
13855 if (item_size < 1)
13856 item_size = old_item_size;
13857
13858 if (num_values < 1)
13859 num_values = old_num_values;
13860
13861 int new_size = num_values * item_size;
13862 char* new_data = (char*)malloc(new_size);
13863 assert(new_data);
13864
13865 memset(new_data, 0, new_size);
13866
13867 if (old_data) {
13868 int num = old_num_values;
13869 if (num > num_values)
13870 num = num_values;
13871
13872 //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);
13873
13874 for (int i=0; i<num; i++) {
13875 const char* old_ptr = old_data + i*old_item_size;
13876 char* new_ptr = new_data + i*item_size;
13877 mstrlcpy(new_ptr, old_ptr, item_size);
13878 }
13879 }
13880
13881 status = db_set_data(hdb, hkey, new_data, new_size, num_values, TID_STRING);
13882
13883 if (old_data)
13884 free(old_data);
13885 if (new_data)
13886 free(new_data);
13887
13888 return status;
13889}
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 9010 of file odb.cxx.

9011{
9012 if (rpc_is_remote() && bRemote)
9013 return rpc_call(RPC_DB_SAVE, hDB, hKey, filename, bRemote);
9014
9015#ifdef LOCAL_ROUTINES
9016 {
9017 INT hfile, size, buffer_size, n, status;
9018 char *buffer;
9019
9020 /* open file */
9021 hfile = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, 0644);
9022 if (hfile == -1) {
9023 cm_msg(MERROR, "db_save", "Cannot open file \"%s\"", filename);
9024 return DB_FILE_ERROR;
9025 }
9026
9027 std::string path = db_get_path(hDB, hKey);
9028
9029 buffer_size = 10000;
9030 do {
9031 buffer = (char *) malloc(buffer_size);
9032 if (buffer == NULL) {
9033 cm_msg(MERROR, "db_save", "cannot allocate ODB dump buffer");
9034 break;
9035 }
9036
9037 size = buffer_size;
9038 status = db_copy(hDB, hKey, buffer, &size, path.c_str());
9039 if (status != DB_TRUNCATED) {
9040 n = write(hfile, buffer, buffer_size - size);
9041 free(buffer);
9042 buffer = NULL;
9043
9044 if (n != buffer_size - size) {
9045 cm_msg(MERROR, "db_save", "cannot save .ODB file");
9046 close(hfile);
9047 return DB_FILE_ERROR;
9048 }
9049 break;
9050 }
9051
9052 /* increase buffer size if truncated */
9053 free(buffer);
9054 buffer = NULL;
9055 buffer_size *= 2;
9056 } while (1);
9057
9058 close(hfile);
9059
9060 }
9061#endif /* LOCAL_ROUTINES */
9062
9063 return DB_SUCCESS;
9064}
#define RPC_DB_SAVE
Definition mrpc.h:74
#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 10295 of file odb.cxx.

10296{
10297 INT status;
10298
10299 /* open file */
10300 FILE *fp = fopen(filename, "w");
10301 if (fp == NULL) {
10302 cm_msg(MERROR, "db_save_json", "Cannot open file \"%s\", fopen() errno %d (%s)", filename, errno, strerror(errno));
10303 return DB_FILE_ERROR;
10304 }
10305
10306 bool unlock = false;
10307
10308 if (!rpc_is_remote()) {
10310 if (status != DB_SUCCESS) {
10311 fclose(fp);
10312 return status;
10313 }
10314 unlock = true;
10315 }
10316
10317 std::string path = db_get_path(hDB, hKey);
10318
10319 bool emptySubdir = false;
10320 HNDLE hSubKey;
10321 status = db_enum_link(hDB, hKey, 0, &hSubKey);
10323 emptySubdir = true;
10324
10325 char* buffer = NULL;
10326 int buffer_size = 0;
10327 int buffer_end = 0;
10328
10329 json_write(&buffer, &buffer_size, &buffer_end, 0, "{\n", 0);
10330
10331 json_write(&buffer, &buffer_size, &buffer_end, 1, "/MIDAS version", 1);
10332 json_write(&buffer, &buffer_size, &buffer_end, 0, " : ", 0);
10333 json_write(&buffer, &buffer_size, &buffer_end, 0, MIDAS_VERSION, 1);
10334 json_write(&buffer, &buffer_size, &buffer_end, 0, ",\n", 0);
10335
10336 json_write(&buffer, &buffer_size, &buffer_end, 1, "/MIDAS git revision", 1);
10337 json_write(&buffer, &buffer_size, &buffer_end, 0, " : ", 0);
10338 json_write(&buffer, &buffer_size, &buffer_end, 0, GIT_REVISION, 1);
10339 json_write(&buffer, &buffer_size, &buffer_end, 0, ",\n", 0);
10340
10341 json_write(&buffer, &buffer_size, &buffer_end, 1, "/filename", 1);
10342 json_write(&buffer, &buffer_size, &buffer_end, 0, " : ", 0);
10343 json_write(&buffer, &buffer_size, &buffer_end, 0, filename, 1);
10344 json_write(&buffer, &buffer_size, &buffer_end, 0, ",\n", 0);
10345
10346 json_write(&buffer, &buffer_size, &buffer_end, 1, "/ODB path", 1);
10347 json_write(&buffer, &buffer_size, &buffer_end, 0, " : ", 0);
10348 json_write(&buffer, &buffer_size, &buffer_end, 0, path.c_str(), 1);
10349
10350 if (emptySubdir)
10351 json_write(&buffer, &buffer_size, &buffer_end, 0, "", 0);
10352 else
10353 json_write(&buffer, &buffer_size, &buffer_end, 0, ",\n", 0);
10354
10355 //status = db_save_json_key_obsolete(hDB, hKey, -1, &buffer, &buffer_size, &buffer_end, 1, 0, 1);
10356 status = json_write_bare_subdir(hDB, hKey, &buffer, &buffer_size, &buffer_end, JS_LEVEL_1, flags, 0);
10357
10358 json_write(&buffer, &buffer_size, &buffer_end, 0, "\n}\n", 0);
10359
10360 if (unlock) {
10362 }
10363
10364 if (status == DB_SUCCESS) {
10365 if (buffer) {
10366 size_t wr = fwrite(buffer, 1, buffer_end, fp);
10367 if (wr != (size_t)buffer_end) {
10368 cm_msg(MERROR, "db_save_json", "Cannot write to file \"%s\", fwrite() errno %d (%s)", filename, errno, strerror(errno));
10369 free(buffer);
10370 fclose(fp);
10371 return DB_FILE_ERROR;
10372 }
10373 }
10374 }
10375
10376 if (buffer)
10377 free(buffer);
10378
10379 fclose(fp);
10380
10381 return DB_SUCCESS;
10382}
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:10122
#define MIDAS_VERSION
Definition midas.h:37
#define JS_LEVEL_1
Definition midas.h:1719
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 9581 of file odb.cxx.

9582{
9583 INT i, size, status;
9584 char *data;
9585 KEY key;
9586 KEY link_key;
9587 char link_path[MAX_ODB_PATH];
9588 int omit_top_level_braces = 0;
9589
9590 //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);
9591
9592 if (level < 0) {
9593 level = 0;
9594 omit_top_level_braces = 1;
9595 }
9596
9598
9599 if (status != DB_SUCCESS)
9600 return status;
9601
9602 link_key = key;
9603
9604 if (key.type == TID_LINK) {
9605 size = sizeof(link_path);
9606 status = db_get_data(hDB, hKey, link_path, &size, TID_LINK);
9607
9608 if (status != DB_SUCCESS)
9609 return status;
9610
9611 if (follow_links) {
9612 status = db_find_key(hDB, 0, link_path, &hKey);
9613
9614 if (status != DB_SUCCESS)
9615 return status;
9616
9618
9619 if (status != DB_SUCCESS)
9620 return status;
9621 }
9622 }
9623
9624 //printf("key [%s] link [%s], type %d, link %d\n", key.name, link_key.name, key.type, link_key.type);
9625
9626 if (key.type == TID_KEY && (recurse || level<=0)) {
9627 int idx = 0;
9628 int do_close_curly_bracket = 0;
9629
9630 if (level == 0 && !omit_top_level_braces) {
9631 json_write(buffer, buffer_size, buffer_end, 0, "{\n", 0);
9632 do_close_curly_bracket = 1;
9633 }
9634 else if (level > 0) {
9635 json_write(buffer, buffer_size, buffer_end, level, link_key.name, 1);
9636 json_write(buffer, buffer_size, buffer_end, 0, " : {\n", 0);
9637 do_close_curly_bracket = 1;
9638 }
9639
9640 if (level > 100) {
9641 std::string path = db_get_path(hDB, hKey);
9642
9643 json_write(buffer, buffer_size, buffer_end, 0, "/error", 1);
9644 json_write(buffer, buffer_size, buffer_end, 0, " : ", 0);
9645 json_write(buffer, buffer_size, buffer_end, 0, "max nesting level exceed", 1);
9646
9647 cm_msg(MERROR, "db_save_json_key", "max nesting level exceeded at \"%s\", check for symlink loops in this subtree", path.c_str());
9648
9649 } else {
9650 HNDLE hSubkey;
9651
9652 for (;; idx++) {
9653 db_enum_link(hDB, hKey, idx, &hSubkey);
9654
9655 if (!hSubkey)
9656 break;
9657
9658 if (idx != 0) {
9659 json_write(buffer, buffer_size, buffer_end, 0, ",\n", 0);
9660 }
9661
9662 /* save subtree */
9663 status = db_save_json_key_obsolete(hDB, hSubkey, level + 1, buffer, buffer_size, buffer_end, save_keys, follow_links, recurse);
9664 if (status != DB_SUCCESS)
9665 return status;
9666 }
9667 }
9668
9669 if (do_close_curly_bracket) {
9670 if (idx > 0)
9671 json_write(buffer, buffer_size, buffer_end, 0, "\n", 0);
9672 json_write(buffer, buffer_size, buffer_end, level, "}", 0);
9673 }
9674
9675 } else {
9676
9677 if (save_keys && level == 0) {
9678 json_write(buffer, buffer_size, buffer_end, 0, "{\n", 0);
9679 }
9680
9681 /* save key value */
9682
9683 if (save_keys == 1) {
9684 char str[NAME_LENGTH+15];
9685 sprintf(str, "%s/key", link_key.name);
9686
9687 json_write(buffer, buffer_size, buffer_end, level, str, 1);
9688 json_write(buffer, buffer_size, buffer_end, 0, " : { ", 0);
9689
9690 sprintf(str, "\"type\" : %d", key.type);
9691 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9692
9693 if (link_key.type == TID_LINK && follow_links) {
9694 json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9695 json_write(buffer, buffer_size, buffer_end, 0, "link", 1);
9696 json_write(buffer, buffer_size, buffer_end, 0, ": ", 0);
9697 json_write(buffer, buffer_size, buffer_end, 0, link_path, 1);
9698 }
9699
9700 if (key.num_values > 1) {
9701 json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9702
9703 sprintf(str, "\"num_values\" : %d", key.num_values);
9704 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9705 }
9706
9707 if (key.type == TID_STRING || key.type == TID_LINK) {
9708 json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9709
9710 sprintf(str, "\"item_size\" : %d", key.item_size);
9711 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9712 }
9713
9714 if (key.notify_count > 0) {
9715 json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9716
9717 sprintf(str, "\"notify_count\" : %d", key.notify_count);
9718 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9719 }
9720
9721 json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9722
9723 sprintf(str, "\"access_mode\" : %d", key.access_mode);
9724 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9725
9726 json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9727
9728 sprintf(str, "\"last_written\" : %d", key.last_written);
9729 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9730
9731 json_write(buffer, buffer_size, buffer_end, 0, " ", 0);
9732
9733 json_write(buffer, buffer_size, buffer_end, 0, "}", 0);
9734
9735 json_write(buffer, buffer_size, buffer_end, 0, ",\n", 0);
9736 }
9737
9738 if (save_keys == 2) {
9739 char str[NAME_LENGTH+15];
9740 sprintf(str, "%s/last_written", link_key.name);
9741
9742 json_write(buffer, buffer_size, buffer_end, level, str, 1);
9743
9744 sprintf(str, " : %d", key.last_written);
9745 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9746
9747 json_write(buffer, buffer_size, buffer_end, 0, ",\n", 0);
9748 }
9749
9750 if (save_keys) {
9751 json_write(buffer, buffer_size, buffer_end, level, link_key.name, 1);
9752 json_write(buffer, buffer_size, buffer_end, 0, " : ", 0);
9753 }
9754
9755 if (key.num_values > 1) {
9756 json_write(buffer, buffer_size, buffer_end, 0, "[ ", 0);
9757 }
9758
9759 size = key.total_size;
9760 data = (char *) malloc(size);
9761 if (data == NULL) {
9762 cm_msg(MERROR, "db_save_json_key", "cannot allocate data buffer for %d bytes", size);
9763 return DB_NO_MEMORY;
9764 }
9765
9766 if (key.type != TID_KEY) {
9767 if (follow_links)
9768 status = db_get_data(hDB, hKey, data, &size, key.type);
9769 else
9771
9772 if (status != DB_SUCCESS)
9773 return status;
9774 }
9775
9776 for (i = 0; i < key.num_values; i++) {
9777 char str[256];
9778 char *p = data + key.item_size*i;
9779
9780 if (i != 0)
9781 json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9782
9783 switch (key.type) {
9784 case TID_UINT8:
9785 sprintf(str, "%u", *(unsigned char*)p);
9786 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9787 break;
9788 case TID_INT8:
9789 sprintf(str, "%d", *(char*)p);
9790 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9791 break;
9792 case TID_CHAR:
9793 sprintf(str, "%c", *(char*)p);
9794 json_write(buffer, buffer_size, buffer_end, 0, str, 1);
9795 break;
9796 case TID_UINT16:
9797 sprintf(str, "\"0x%04x\"", *(WORD*)p);
9798 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9799 break;
9800 case TID_INT16:
9801 sprintf(str, "%d", *(short*)p);
9802 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9803 break;
9804 case TID_UINT32:
9805 sprintf(str, "\"0x%08x\"", *(DWORD*)p);
9806 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9807 break;
9808 case TID_INT32:
9809 sprintf(str, "%d", *(int*)p);
9810 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9811 break;
9812 case TID_UINT64:
9813 sprintf(str, "\"0x%08llx\"", *(UINT64*)p);
9814 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9815 break;
9816 case TID_INT64:
9817 sprintf(str, "%lld", *(INT64*)p);
9818 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9819 break;
9820 case TID_BOOL:
9821 if (*(int*)p)
9822 json_write(buffer, buffer_size, buffer_end, 0, "true", 0);
9823 else
9824 json_write(buffer, buffer_size, buffer_end, 0, "false", 0);
9825 break;
9826 case TID_FLOAT: {
9827 float flt = (*(float*)p);
9828 if (isnan(flt))
9829 json_write(buffer, buffer_size, buffer_end, 0, "\"NaN\"", 0);
9830 else if (isinf(flt)) {
9831 if (flt > 0)
9832 json_write(buffer, buffer_size, buffer_end, 0, "\"Infinity\"", 0);
9833 else
9834 json_write(buffer, buffer_size, buffer_end, 0, "\"-Infinity\"", 0);
9835 } else if (flt == 0)
9836 json_write(buffer, buffer_size, buffer_end, 0, "0", 0);
9837 else if (flt == (int)flt) {
9838 sprintf(str, "%.0f", flt);
9839 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9840 } else {
9841 sprintf(str, "%.7e", flt);
9842 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9843 }
9844 break;
9845 }
9846 case TID_DOUBLE: {
9847 double dbl = (*(double*)p);
9848 if (isnan(dbl))
9849 json_write(buffer, buffer_size, buffer_end, 0, "\"NaN\"", 0);
9850 else if (isinf(dbl)) {
9851 if (dbl > 0)
9852 json_write(buffer, buffer_size, buffer_end, 0, "\"Infinity\"", 0);
9853 else
9854 json_write(buffer, buffer_size, buffer_end, 0, "\"-Infinity\"", 0);
9855 } else if (dbl == 0)
9856 json_write(buffer, buffer_size, buffer_end, 0, "0", 0);
9857 else if (dbl == (int)dbl) {
9858 sprintf(str, "%.0f", dbl);
9859 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9860 } else {
9861 sprintf(str, "%.16e", dbl);
9862 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9863 }
9864 break;
9865 }
9866 case TID_BITFIELD:
9867 json_write(buffer, buffer_size, buffer_end, 0, "(TID_BITFIELD value)", 1);
9868 break;
9869 case TID_STRING:
9870 p[key.item_size-1] = 0; // make sure string is NUL terminated!
9871 json_write(buffer, buffer_size, buffer_end, 0, p, 1);
9872 break;
9873 case TID_ARRAY:
9874 json_write(buffer, buffer_size, buffer_end, 0, "(TID_ARRAY value)", 1);
9875 break;
9876 case TID_STRUCT:
9877 json_write(buffer, buffer_size, buffer_end, 0, "(TID_STRUCT value)", 1);
9878 break;
9879 case TID_KEY:
9880 json_write(buffer, buffer_size, buffer_end, 0, "{ }", 0);
9881 break;
9882 case TID_LINK:
9883 p[key.item_size-1] = 0; // make sure string is NUL terminated!
9884 json_write(buffer, buffer_size, buffer_end, 0, p, 1);
9885 break;
9886 default:
9887 json_write(buffer, buffer_size, buffer_end, 0, "(TID_UNKNOWN value)", 1);
9888 }
9889
9890 }
9891
9892 if (key.num_values > 1) {
9893 json_write(buffer, buffer_size, buffer_end, 0, " ]", 0);
9894 } else {
9895 json_write(buffer, buffer_size, buffer_end, 0, "", 0);
9896 }
9897
9898 free(data);
9899 data = NULL;
9900
9901 if (save_keys && level == 0) {
9902 json_write(buffer, buffer_size, buffer_end, 0, "\n}", 0);
9903 }
9904 }
9905
9906 return DB_SUCCESS;
9907}
#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 10456 of file odb.cxx.

10479{
10480 KEY key;
10481 char str[256], line[50+256];
10482 INT status, i, size, fh, buffer_size;
10483 char *buffer = NULL, *pc;
10484 int wr;
10485
10486
10487 /* open file */
10488 fh = open(file_name, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0644);
10489
10490 if (fh == -1) {
10491 cm_msg(MERROR, "db_save_string", "Cannot open file\"%s\"", file_name);
10492 return DB_FILE_ERROR;
10493 }
10494
10496 if (status != DB_SUCCESS) {
10497 cm_msg(MERROR, "db_save_string", "cannot find key");
10498 return DB_INVALID_HANDLE;
10499 }
10500
10501 if (string_name && string_name[0])
10502 strcpy(str, string_name);
10503 else
10504 strcpy(str, key.name);
10505
10506 name2c(str);
10507 for (i = 0; i < (int) strlen(str); i++)
10508 str[i] = (char) toupper(str[i]);
10509
10510 sprintf(line, "#define %s(_name) const char *_name[] = {\\\n", str);
10511 size = strlen(line);
10512 wr = write(fh, line, size);
10513 if (wr != size) {
10514 cm_msg(MERROR, "db_save", "file \"%s\" write error: write(%d) returned %d, errno %d (%s)", file_name, size, wr, errno, strerror(errno));
10515 close(fh);
10516 if (buffer)
10517 free(buffer);
10518 return DB_FILE_ERROR;
10519 }
10520
10521 buffer_size = 10000;
10522 do {
10523 buffer = (char *) malloc(buffer_size);
10524 if (buffer == NULL) {
10525 cm_msg(MERROR, "db_save", "cannot allocate ODB dump buffer");
10526 break;
10527 }
10528
10529 size = buffer_size;
10530 status = db_copy(hDB, hKey, buffer, &size, "");
10531 if (status != DB_TRUNCATED)
10532 break;
10533
10534 /* increase buffer size if truncated */
10535 free(buffer);
10536 buffer = NULL;
10537 buffer_size *= 2;
10538 } while (1);
10539
10540
10541 pc = buffer;
10542
10543 do {
10544 i = 0;
10545 line[i++] = '"';
10546 while (*pc != '\n' && *pc != 0) {
10547 if (*pc == '\"' || *pc == '\'')
10548 line[i++] = '\\';
10549 line[i++] = *pc++;
10550 }
10551 strcpy(&line[i], "\",\\\n");
10552 if (i > 0) {
10553 size = strlen(line);
10554 wr = write(fh, line, size);
10555 if (wr != size) {
10556 cm_msg(MERROR, "db_save", "file \"%s\" write error: write(%d) returned %d, errno %d (%s)", file_name, size, wr, errno, strerror(errno));
10557 close(fh);
10558 if (buffer)
10559 free(buffer);
10560 return DB_FILE_ERROR;
10561 }
10562 }
10563
10564 if (*pc == '\n')
10565 pc++;
10566
10567 } while (*pc);
10568
10569 sprintf(line, "NULL }\n\n");
10570 size = strlen(line);
10571 wr = write(fh, line, size);
10572 if (wr != size) {
10573 cm_msg(MERROR, "db_save", "file \"%s\" write error: write(%d) returned %d, errno %d (%s)", file_name, size, wr, errno, strerror(errno));
10574 close(fh);
10575 if (buffer)
10576 free(buffer);
10577 return DB_FILE_ERROR;
10578 }
10579
10580 close(fh);
10581 free(buffer);
10582
10583 return DB_SUCCESS;
10584}
void name2c(char *str)
Definition odb.cxx:8862
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 10395 of file odb.cxx.

10396{
10397 KEY key;
10398 char str[100], line[10+100];
10399 INT status, i, fh;
10400 int wr, size;
10401
10402 /* open file */
10403 fh = open(file_name, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0644);
10404
10405 if (fh == -1) {
10406 cm_msg(MERROR, "db_save_struct", "Cannot open file\"%s\"", file_name);
10407 return DB_FILE_ERROR;
10408 }
10409
10411 if (status != DB_SUCCESS) {
10412 cm_msg(MERROR, "db_save_struct", "cannot find key");
10413 return DB_INVALID_HANDLE;
10414 }
10415
10416 sprintf(line, "typedef struct {\n");
10417
10418 size = strlen(line);
10419 wr = write(fh, line, size);
10420 if (wr != size) {
10421 cm_msg(MERROR, "db_save_struct", "file \"%s\" write error: write(%d) returned %d, errno %d (%s)", file_name, size, wr, errno, strerror(errno));
10422 close(fh);
10423 return DB_FILE_ERROR;
10424 }
10425
10426 db_save_tree_struct(hDB, hKey, fh, 0);
10427
10428 if (struct_name && struct_name[0])
10429 mstrlcpy(str, struct_name, sizeof(str));
10430 else
10431 mstrlcpy(str, key.name, sizeof(str));
10432
10433 name2c(str);
10434 for (i = 0; i < (int) strlen(str); i++)
10435 str[i] = (char) toupper(str[i]);
10436
10437 sprintf(line, "} %s;\n\n", str);
10438
10439 size = strlen(line);
10440 wr = write(fh, line, size);
10441 if (wr != size) {
10442 cm_msg(MERROR, "db_save_struct", "file \"%s\" write error: write(%d) returned %d, errno %d (%s)", file_name, size, wr, errno, strerror(errno));
10443 close(fh);
10444 return DB_FILE_ERROR;
10445 }
10446
10447 close(fh);
10448
10449 return DB_SUCCESS;
10450}
static void db_save_tree_struct(HNDLE hDB, HNDLE hKey, int hfile, INT level)
Definition odb.cxx:8883
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 8883 of file odb.cxx.

8892{
8893 INT i, idx;
8894 KEY key;
8895 HNDLE hSubkey;
8896 int wr;
8897
8898 /* first enumerate this level */
8899 for (idx = 0;; idx++) {
8900 char name[MAX_ODB_PATH];
8901
8902 db_enum_link(hDB, hKey, idx, &hSubkey);
8903 if (!hSubkey)
8904 break;
8905
8906 /* first get the name of the link, than the type of the link target */
8908 mstrlcpy(name, key.name, sizeof(name));
8909 db_enum_key(hDB, hKey, idx, &hSubkey);
8910
8912
8913 if (key.type != TID_KEY) {
8914 char line[MAX_ODB_PATH];
8915 char str[MAX_ODB_PATH];
8916
8917 for (i = 0; i <= level; i++) {
8918 wr = write(hfile, " ", 2);
8919 assert(wr == 2);
8920 }
8921
8922 switch (key.type) {
8923 case TID_INT8:
8924 case TID_CHAR:
8925 strcpy(line, "char");
8926 break;
8927 case TID_INT16:
8928 strcpy(line, "short");
8929 break;
8930 case TID_FLOAT:
8931 strcpy(line, "float");
8932 break;
8933 case TID_DOUBLE:
8934 strcpy(line, "double");
8935 break;
8936 case TID_BITFIELD:
8937 strcpy(line, "unsigned char");
8938 break;
8939 case TID_STRING:
8940 strcpy(line, "char");
8941 break;
8942 case TID_LINK:
8943 strcpy(line, "char");
8944 break;
8945 default:
8946 strcpy(line, rpc_tid_name(key.type));
8947 break;
8948 }
8949
8950 mstrlcat(line, " ", sizeof(line));
8951 mstrlcpy(str, name, sizeof(str));
8952 name2c(str);
8953
8954 if (key.num_values > 1)
8955 sprintf(str + strlen(str), "[%d]", key.num_values);
8956 if (key.type == TID_STRING || key.type == TID_LINK)
8957 sprintf(str + strlen(str), "[%d]", key.item_size);
8958
8959 mstrlcpy(line + 10, str, sizeof(line) - 10);
8960 mstrlcat(line, ";\n", sizeof(line));
8961
8962 wr = write(hfile, line, strlen(line));
8963 assert(wr > 0);
8964 } else {
8965 char line[10+MAX_ODB_PATH];
8966 char str[MAX_ODB_PATH];
8967
8968 /* recurse subtree */
8969 for (i = 0; i <= level; i++) {
8970 wr = write(hfile, " ", 2);
8971 assert(wr == 2);
8972 }
8973
8974 sprintf(line, "struct {\n");
8975 wr = write(hfile, line, strlen(line));
8976 assert(wr > 0);
8977 db_save_tree_struct(hDB, hSubkey, hfile, level + 1);
8978
8979 for (i = 0; i <= level; i++) {
8980 wr = write(hfile, " ", 2);
8981 assert(wr == 2);
8982 }
8983
8984 strcpy(str, name);
8985 name2c(str);
8986
8987 sprintf(line, "} %s;\n", str);
8988 wr = write(hfile, line, strlen(line));
8989 assert(wr > 0);
8990 }
8991 }
8992}
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 9250 of file odb.cxx.

9251{
9252#ifdef LOCAL_ROUTINES
9253 {
9254 INT status;
9255 MXML_WRITER *writer;
9256
9257 /* open file */
9258 writer = mxml_open_file(filename);
9259 if (writer == NULL) {
9260 cm_msg(MERROR, "db_save_xml", "Cannot open file \"%s\"", filename);
9261 return DB_FILE_ERROR;
9262 }
9263
9264 std::string path = db_get_path(hDB, hKey);
9265
9266 /* write XML header */
9267 mxml_start_element(writer, "odb");
9268 mxml_write_attribute(writer, "root", path.c_str());
9269 mxml_write_attribute(writer, "filename", filename);
9270 mxml_write_attribute(writer, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
9271
9272 std::string xsd_path;
9273
9274 if (getenv("MIDASSYS"))
9275 xsd_path = getenv("MIDASSYS");
9276 else
9277 xsd_path = ".";
9278
9279 xsd_path += DIR_SEPARATOR_STR;
9280 xsd_path += "odb.xsd";
9281 mxml_write_attribute(writer, "xsi:noNamespaceSchemaLocation", xsd_path.c_str());
9282
9283 status = db_save_xml_key(hDB, hKey, 0, writer);
9284
9285 mxml_end_element(writer); // "odb"
9286 mxml_close_file(writer);
9287
9288 return status;
9289 }
9290#endif /* LOCAL_ROUTINES */
9291
9292 return DB_SUCCESS;
9293}
#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 9111 of file odb.cxx.

9112{
9113 INT i, idx, size, status;
9114 char *data;
9115 HNDLE hSubkey;
9116 KEY key;
9117
9118 if (level > MAX_ODB_PATH) {
9119 cm_msg(MERROR, "db_save_xml_key", "ODB path too long at \"%s\"", db_get_path(hDB, hKey).c_str());
9120 return DB_NO_MEMORY;
9121 }
9122
9124 if (status != DB_SUCCESS)
9125 return status;
9126
9127 if (key.type == TID_KEY) {
9128
9129 /* save opening tag for subtree */
9130
9131 if (level > 0) {
9132 mxml_start_element(writer, "dir");
9133 mxml_write_attribute(writer, "name", key.name);
9134 mxml_write_attribute(writer, "handle", std::to_string(hKey).c_str());
9135 }
9136
9137 for (idx = 0;; idx++) {
9138 db_enum_link(hDB, hKey, idx, &hSubkey);
9139
9140 if (!hSubkey)
9141 break;
9142
9143 /* save subtree */
9144 status = db_save_xml_key(hDB, hSubkey, level + 1, writer);
9145 if (status != DB_SUCCESS)
9146 return status;
9147 }
9148
9149 /* save closing tag for subtree */
9150 if (level > 0)
9151 mxml_end_element(writer);
9152
9153 } else {
9154 /* save key value */
9155
9156 if (key.num_values > 1)
9157 mxml_start_element(writer, "keyarray");
9158 else
9159 mxml_start_element(writer, "key");
9160 mxml_write_attribute(writer, "name", key.name);
9161 mxml_write_attribute(writer, "type", rpc_tid_name(key.type));
9162 mxml_write_attribute(writer, "handle", std::to_string(hKey).c_str());
9163
9164 if (key.type == TID_STRING || key.type == TID_LINK) {
9165 char str[256];
9166 sprintf(str, "%d", key.item_size);
9167 mxml_write_attribute(writer, "size", str);
9168 }
9169
9170 if (key.num_values > 1) {
9171 char str[256];
9172 sprintf(str, "%d", key.num_values);
9173 mxml_write_attribute(writer, "num_values", str);
9174 }
9175
9176 size = key.total_size;
9177 data = (char *) malloc(size+1); // an extra byte to zero-terminate strings
9178 if (data == NULL) {
9179 cm_msg(MERROR, "db_save_xml_key", "cannot allocate data buffer");
9180 return DB_NO_MEMORY;
9181 }
9182
9183 db_get_link_data(hDB, hKey, data, &size, key.type);
9184
9185 if (key.num_values == 1) {
9186 if (key.type == TID_STRING) {
9187 data[size] = 0; // make sure strings are NUL-terminated
9188 mxml_write_value(writer, data);
9189 } else {
9190 std::string str = db_sprintf(data, key.item_size, 0, key.type);
9191 if (key.type == TID_STRING && strlen(data) >= MAX_STRING_LENGTH) {
9192 std::string path = db_get_path(hDB, hKey);
9193 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());
9194 }
9195 mxml_write_value(writer, str.c_str());
9196 }
9197 mxml_end_element(writer);
9198
9199 } else { /* array of values */
9200
9201 for (i = 0; i < key.num_values; i++) {
9202
9203 mxml_start_element(writer, "value");
9204
9205 {
9206 char str[256];
9207 sprintf(str, "%d", i);
9208 mxml_write_attribute(writer, "index", str);
9209 }
9210
9211 if (key.type == TID_STRING) {
9212 char* p = data + i * key.item_size;
9213 p[key.item_size - 1] = 0; // make sure string is NUL-terminated
9214 //cm_msg(MINFO, "db_save_xml_key", "odb string array item_size %d, index %d length %d", key.item_size, i, (int)strlen(p));
9215 mxml_write_value(writer, p);
9216 } else {
9217 std::string str = db_sprintf(data, key.item_size, i, key.type);
9218 if ((key.type == TID_STRING) && (str.length() >= MAX_STRING_LENGTH-1)) {
9219 std::string path = db_get_path(hDB, hKey);
9220 cm_msg(MERROR, "db_save_xml_key", "Long odb string array probably truncated, odb path \"%s\"[%d]", path.c_str(), i);
9221 }
9222 mxml_write_value(writer, str.c_str());
9223 }
9224
9225 mxml_end_element(writer);
9226 }
9227
9228 mxml_end_element(writer); /* keyarray */
9229 }
9230
9231 free(data);
9232 data = NULL;
9233 }
9234
9235 return DB_SUCCESS;
9236}
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 13891 of file odb.cxx.

13892{
13893#ifdef LOCAL_ROUTINES
13894 MJsonNode* scl = MJsonNode::MakeObject();
13895 MJsonNode* clients = MJsonNode::MakeArray();
13896
13897 scl->AddToObject("now", MJsonNode::MakeNumber(ss_time_sec()));
13898 scl->AddToObject("clients", clients);
13899
13900 /* lock database */
13902
13903 DATABASE *pdb = &_database[hDB - 1];
13904 DATABASE_HEADER *pheader = pdb->database_header;
13905
13906 DWORD now = ss_millitime();
13907
13908 /* list clients */
13909 for (int i = 0; i < pheader->max_client_index; i++) {
13910 DATABASE_CLIENT *pclient = &pheader->client[i];
13911 if (pclient->pid) {
13912 MJsonNode* c = MJsonNode::MakeObject();
13913 c->AddToObject("slot", MJsonNode::MakeNumber(i));
13914 c->AddToObject("pid", MJsonNode::MakeNumber(pclient->pid));
13915 c->AddToObject("name", MJsonNode::MakeString(pclient->name));
13916 std::string path = msprintf("/System/Clients/%d/Host", pclient->pid);
13917 const KEY* pkey = db_find_pkey_locked(pheader, NULL, path.c_str(), true, NULL, NULL);
13918 if (pkey) {
13919 int host_size = pkey->total_size;
13920 char* host = (char*)malloc(host_size);
13921 assert(host != NULL);
13922 db_get_data_locked(pheader, pkey, 0, host, &host_size, TID_STRING, NULL);
13923 c->AddToObject("host", MJsonNode::MakeString(host));
13924 free(host);
13925 }
13926 c->AddToObject("watchdog_timeout_millisec", MJsonNode::MakeNumber(pclient->watchdog_timeout));
13927 // "now" and "last_activity" is millisecond time wrapped around at 32 bits, must do unsigned 32-bit math here, not in javascript
13928 c->AddToObject("last_activity_millisec", MJsonNode::MakeNumber(now - pclient->last_activity));
13929 clients->AddToArray(c);
13930 }
13931 }
13932
13934
13935 return scl;
13936#else
13937 return MJsonNode::MakeNull();
13938#endif
13939}
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:2293
INT cm_disconnect_experiment(void)
Definition midas.cxx:2861
INT cm_get_environment(char *host_name, int host_name_size, char *exp_name, int exp_name_size)
Definition midas.cxx:2149
#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 13556 of file odb.cxx.

13557{
13558 INT i;
13559
13560 for (i = 0; i < _record_list_entries; i++)
13561 if (_record_list[i].access_mode & MODE_WRITE) {
13562 if (memcmp(_record_list[i].copy, _record_list[i].data, _record_list[i].buf_size) != 0) {
13563 if (rpc_is_remote()) {
13564 int align = ss_get_struct_align();
13566 } else {
13568 }
13569 memcpy(_record_list[i].copy, _record_list[i].data, _record_list[i].buf_size);
13570 }
13571 }
13572
13573 return DB_SUCCESS;
13574}
#define RPC_NO_REPLY
Definition midas.h:396
#define RPC_DB_SET_RECORD
Definition mrpc.h:71
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_client_name()

INT db_set_client_name ( HNDLE  hDB,
const char *  client_name 
)

Definition at line 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:76
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_data()

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

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

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

Definition at line 6986 of file odb.cxx.

6987{
6988 if (rpc_is_remote())
6989 return rpc_call(RPC_DB_SET_DATA, hDB, hKey, data, buf_size, num_values, type);
6990
6991#ifdef LOCAL_ROUTINES
6992 {
6993 HNDLE hkeylink;
6994 int link_idx;
6995 int status;
6996
6997 if (hDB > _database_entries || hDB <= 0) {
6998 cm_msg(MERROR, "db_set_data", "invalid database handle");
6999 return DB_INVALID_HANDLE;
7000 }
7001
7002 if (!_database[hDB - 1].attached) {
7003 cm_msg(MERROR, "db_set_data", "invalid database handle");
7004 return DB_INVALID_HANDLE;
7005 }
7006
7007 if (hKey < (int) sizeof(DATABASE_HEADER)) {
7008 cm_msg(MERROR, "db_set_data", "invalid key handle");
7009 return DB_INVALID_HANDLE;
7010 }
7011
7012 if (num_values == 0)
7013 return DB_INVALID_PARAM;
7014
7016 db_err_msg* msg = NULL;
7017
7018
7019 DATABASE* pdb = &_database[hDB - 1];
7020 DATABASE_HEADER* pheader = pdb->database_header;
7021
7022 /* check if hKey argument is correct */
7023 if (!db_validate_hkey(pheader, hKey)) {
7025 return DB_INVALID_HANDLE;
7026 }
7027
7028 KEY* pkey = (KEY *) ((char *) pheader + hKey);
7029
7030 /* check for write access */
7031 if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
7033 return DB_NO_ACCESS;
7034 }
7035
7036 /* check for link to array index */
7037 if (pkey->type == TID_LINK) {
7038 char link_name[256]; // FIXME: use std::string
7039 mstrlcpy(link_name, (char *) pheader + pkey->data, sizeof(link_name));
7040 if (strlen(link_name) > 0 && link_name[strlen(link_name) - 1] == ']') {
7042 if (strchr(link_name, '[') == NULL)
7043 return DB_INVALID_LINK;
7044 link_idx = atoi(strchr(link_name, '[') + 1);
7045 *strchr(link_name, '[') = 0;
7046 if (db_find_key(hDB, 0, link_name, &hkeylink) != DB_SUCCESS)
7047 return DB_INVALID_LINK;
7048 return db_set_data_index(hDB, hkeylink, data, buf_size, link_idx, type);
7049 }
7050 }
7051
7052 status = db_check_set_data_locked(pheader, pkey, data, buf_size, num_values, type, "db_set_data", &msg);
7053
7054 if (status != DB_SUCCESS) {
7056 if (msg)
7057 db_flush_msg(&msg);
7058 return status;
7059 }
7060
7061 db_allow_write_locked(pdb, "db_set_data");
7062
7063 status = db_set_data_wlocked(pheader, pkey, data, buf_size, num_values, type, "db_set_data", &msg);
7064
7065 if (status != DB_SUCCESS) {
7067 if (msg)
7068 db_flush_msg(&msg);
7069 return status;
7070 }
7071
7072 db_notify_clients_locked(pdb, hKey, -1, TRUE, &msg);
7074 if (msg)
7075 db_flush_msg(&msg);
7076
7077
7078 }
7079#endif /* LOCAL_ROUTINES */
7080
7081 return DB_SUCCESS;
7082}
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:6872
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:6785
#define RPC_DB_SET_DATA
Definition mrpc.h:66
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_data1()

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

Definition at line 7084 of file odb.cxx.

7090{
7091 if (rpc_is_remote())
7092 return rpc_call(RPC_DB_SET_DATA1, hDB, hKey, data, buf_size, num_values, type);
7093
7094#ifdef LOCAL_ROUTINES
7095 {
7096 DATABASE_HEADER *pheader;
7097 KEY *pkey;
7098 HNDLE hkeylink;
7099 int link_idx;
7100 char link_name[256];
7101 int status;
7102
7103 if (hDB > _database_entries || hDB <= 0) {
7104 cm_msg(MERROR, "db_set_data1", "invalid database handle");
7105 return DB_INVALID_HANDLE;
7106 }
7107
7108 if (!_database[hDB - 1].attached) {
7109 cm_msg(MERROR, "db_set_data1", "invalid database handle");
7110 return DB_INVALID_HANDLE;
7111 }
7112
7113 if (hKey < (int) sizeof(DATABASE_HEADER)) {
7114 cm_msg(MERROR, "db_set_data1", "invalid key handle");
7115 return DB_INVALID_HANDLE;
7116 }
7117
7118 if (num_values == 0)
7119 return DB_INVALID_PARAM;
7120
7122 db_err_msg* msg = NULL;
7123
7124 pheader = _database[hDB - 1].database_header;
7125
7126 /* check if hKey argument is correct */
7127 if (!db_validate_hkey(pheader, hKey)) {
7129 return DB_INVALID_HANDLE;
7130 }
7131
7132 pkey = (KEY *) ((char *) pheader + hKey);
7133
7134 /* check for write access */
7135 if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
7137 return DB_NO_ACCESS;
7138 }
7139
7140 /* check for link to array index */
7141 if (pkey->type == TID_LINK) {
7142 mstrlcpy(link_name, (char *) pheader + pkey->data, sizeof(link_name));
7143 if (strlen(link_name) > 0 && link_name[strlen(link_name) - 1] == ']') {
7145 if (strchr(link_name, '[') == NULL)
7146 return DB_INVALID_LINK;
7147 link_idx = atoi(strchr(link_name, '[') + 1);
7148 *strchr(link_name, '[') = 0;
7149 if (db_find_key(hDB, 0, link_name, &hkeylink) != DB_SUCCESS)
7150 return DB_INVALID_LINK;
7151 return db_set_data_index1(hDB, hkeylink, data, buf_size, link_idx, type, FALSE);
7152 }
7153 }
7154
7155 status = db_check_set_data_locked(pheader, pkey, data, buf_size, num_values, type, "db_set_data1", &msg);
7156
7157 if (status != DB_SUCCESS) {
7159 if (msg)
7160 db_flush_msg(&msg);
7161 return status;
7162 }
7163
7164 db_allow_write_locked(&_database[hDB - 1], "db_set_data1");
7165
7166 status = db_set_data_wlocked(pheader, pkey, data, buf_size, num_values, type, "db_set_data1", &msg);
7167
7168 if (status != DB_SUCCESS) {
7170 if (msg)
7171 db_flush_msg(&msg);
7172 return status;
7173 }
7174
7176 if (msg)
7177 db_flush_msg(&msg);
7178
7179 }
7180#endif /* LOCAL_ROUTINES */
7181
7182 return DB_SUCCESS;
7183}
INT db_set_data_index1(HNDLE hDB, HNDLE hKey, const void *data, INT data_size, INT idx, DWORD type, BOOL bNotify)
Definition odb.cxx:7591
#define RPC_DB_SET_DATA1
Definition mrpc.h:95
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_data_index()

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

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

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

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

Definition at line 7415 of file odb.cxx.

7416{
7417 if (rpc_is_remote())
7418 return rpc_call(RPC_DB_SET_DATA_INDEX, hDB, hKey, data, data_size, idx, type);
7419
7420#ifdef LOCAL_ROUTINES
7421 {
7422 int link_idx;
7423 HNDLE hkeylink;
7424 int status;
7425
7426 if (hDB > _database_entries || hDB <= 0) {
7427 cm_msg(MERROR, "db_set_data_index", "invalid database handle");
7428 return DB_INVALID_HANDLE;
7429 }
7430
7431 if (!_database[hDB - 1].attached) {
7432 cm_msg(MERROR, "db_set_data_index", "invalid database handle");
7433 return DB_INVALID_HANDLE;
7434 }
7435
7436 if (hKey < (int) sizeof(DATABASE_HEADER)) {
7437 cm_msg(MERROR, "db_set_data_index", "invalid key handle");
7438 return DB_INVALID_HANDLE;
7439 }
7440
7442 db_err_msg* msg = NULL;
7443
7444 DATABASE* pdb = &_database[hDB - 1];
7445 DATABASE_HEADER* pheader = pdb->database_header;
7446
7447 /* check if hKey argument is correct */
7448 if (!db_validate_hkey(pheader, hKey)) {
7450 return DB_INVALID_HANDLE;
7451 }
7452
7453 KEY* pkey = (KEY *) ((char *) pheader + hKey);
7454
7455 /* check for write access */
7456 if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
7458 return DB_NO_ACCESS;
7459 }
7460
7461 /* check for link to array index */
7462 if (pkey->type == TID_LINK) {
7463 char link_name[256]; // FIXME: use std::string
7464 mstrlcpy(link_name, (char *) pheader + pkey->data, sizeof(link_name));
7465 if (strlen(link_name) > 0 && link_name[strlen(link_name) - 1] == ']') {
7467 if (strchr(link_name, '[') == NULL)
7468 return DB_INVALID_LINK;
7469 link_idx = atoi(strchr(link_name, '[') + 1);
7470 *strchr(link_name, '[') = 0;
7471 if (db_find_key(hDB, 0, link_name, &hkeylink) != DB_SUCCESS)
7472 return DB_INVALID_LINK;
7473 return db_set_data_index(hDB, hkeylink, data, data_size, link_idx, type);
7474 }
7475 }
7476
7477 status = db_check_set_data_index_locked(pheader, pkey, idx, data, data_size, type, "db_set_data_index", &msg);
7478
7479 if (status != DB_SUCCESS) {
7481 if (msg)
7482 db_flush_msg(&msg);
7483 return status;
7484 }
7485
7486 db_allow_write_locked(&_database[hDB-1], "db_set_data_index");
7487
7488 status = db_set_data_index_wlocked(pheader, pkey, idx, data, data_size, type, "db_set_data_index", &msg);
7489
7490 if (status != DB_SUCCESS) {
7492 if (msg)
7493 db_flush_msg(&msg);
7494 return status;
7495 }
7496
7497 db_notify_clients_locked(pdb, hKey, idx, TRUE, &msg);
7499 if (msg)
7500 db_flush_msg(&msg);
7501
7502 }
7503#endif /* LOCAL_ROUTINES */
7504
7505 return DB_SUCCESS;
7506}
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:6828
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:6919
#define RPC_DB_SET_DATA_INDEX
Definition mrpc.h:67
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_data_index1()

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

dox

Definition at line 7591 of file odb.cxx.

7618{
7619 if (rpc_is_remote())
7620 return rpc_call(RPC_DB_SET_DATA_INDEX1, hDB, hKey, data, data_size, idx, type, bNotify);
7621
7622#ifdef LOCAL_ROUTINES
7623 {
7624 if (hDB > _database_entries || hDB <= 0) {
7625 cm_msg(MERROR, "db_set_data_index1", "invalid database handle");
7626 return DB_INVALID_HANDLE;
7627 }
7628
7629 if (!_database[hDB - 1].attached) {
7630 cm_msg(MERROR, "db_set_data_index1", "invalid database handle");
7631 return DB_INVALID_HANDLE;
7632 }
7633
7634 if (hKey < (int) sizeof(DATABASE_HEADER)) {
7635 cm_msg(MERROR, "db_set_data_index1", "invalid key handle");
7636 return DB_INVALID_HANDLE;
7637 }
7638
7640 db_err_msg* msg = NULL;
7641
7642 DATABASE* pdb = &_database[hDB - 1];
7643 DATABASE_HEADER* pheader = pdb->database_header;
7644
7645 /* check if hKey argument is correct */
7646 if (!db_validate_hkey(pheader, hKey)) {
7648 return DB_INVALID_HANDLE;
7649 }
7650
7651 KEY* pkey = (KEY *) ((char *) pheader + hKey);
7652
7653 int status = db_check_set_data_index_locked(pheader, pkey, idx, data, data_size, type, "db_set_data_index1", &msg);
7654
7655 if (status != DB_SUCCESS) {
7657 if (msg)
7658 db_flush_msg(&msg);
7659 return status;
7660 }
7661
7662 db_allow_write_locked(pdb, "db_set_data_index1");
7663
7664 status = db_set_data_index_wlocked(pheader, pkey, idx, data, data_size, type, "db_set_data_index1", &msg);
7665
7666 if (status != DB_SUCCESS) {
7668 if (msg)
7669 db_flush_msg(&msg);
7670 return status;
7671 }
7672
7673 if (bNotify)
7674 db_notify_clients_locked(pdb, hKey, idx, TRUE, &msg);
7675
7677 if (msg)
7678 db_flush_msg(&msg);
7679
7680 }
7681#endif /* LOCAL_ROUTINES */
7682
7683 return DB_SUCCESS;
7684}
#define RPC_DB_SET_DATA_INDEX1
Definition mrpc.h:85
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_data_index_wlocked()

static INT db_set_data_index_wlocked ( DATABASE_HEADER pheader,
KEY pkey,
int  idx,
const void *  data,
INT  data_size,
DWORD  type,
const char *  caller,
db_err_msg **  msg 
)
static

Definition at line 6828 of file odb.cxx.

6829{
6830 /* increase key size if necessary */
6831 if (idx >= pkey->num_values || pkey->item_size == 0) {
6832 // FIXME: validate pkey->data
6833 pkey->data = (POINTER_T) realloc_data(pheader, (char *) pheader + pkey->data, pkey->total_size, data_size * (idx + 1), caller);
6834
6835 if (pkey->data == 0) {
6836 pkey->total_size = 0;
6837 pkey->num_values = 0;
6838 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));
6839 return DB_FULL;
6840 }
6841
6842 pkey->data -= (POINTER_T) pheader;
6843 if (!pkey->item_size)
6844 pkey->item_size = data_size;
6845 pkey->total_size = data_size * (idx + 1);
6846 pkey->num_values = idx + 1;
6847 }
6848
6849#if 0
6850 /* cut strings which are too long */
6851 if ((type == TID_STRING || type == TID_LINK) && (int) strlen((char *) data) + 1 > pkey->item_size)
6852 *((char *) data + pkey->item_size - 1) = 0;
6853
6854 /* copy data */
6855 memcpy((char *) pheader + pkey->data + idx * pkey->item_size, data, pkey->item_size);
6856#endif
6857
6858 if ((type == TID_STRING || type == TID_LINK)) {
6859 /* cut strings which are too long */
6860 mstrlcpy((char *) pheader + pkey->data + idx * pkey->item_size, (char*)data, pkey->item_size);
6861 } else {
6862 /* copy data */
6863 memcpy((char *) pheader + pkey->data + idx * pkey->item_size, data, pkey->item_size);
6864 }
6865
6866 /* update time */
6867 pkey->last_written = ss_time();
6868
6869 return DB_SUCCESS;
6870}
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 6785 of file odb.cxx.

6786{
6787 /* if no buf_size given (Java!), calculate it */
6788 if (data_size == 0)
6789 data_size = pkey->item_size * num_values;
6790
6791 /* resize data size if necessary */
6792 if (pkey->total_size != data_size) {
6793 // FIXME: validate pkey->data!
6794 pkey->data = (POINTER_T) realloc_data(pheader, (char *) pheader + pkey->data, pkey->total_size, data_size, caller);
6795
6796 if (pkey->data == 0) {
6797 pkey->total_size = 0;
6798 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);
6799 return DB_FULL;
6800 }
6801
6802 pkey->data -= (POINTER_T) pheader;
6803 pkey->total_size = data_size;
6804 }
6805
6806 /* set number of values */
6807 pkey->num_values = num_values;
6808
6809 if (type == TID_STRING || type == TID_LINK)
6810 pkey->item_size = data_size / num_values;
6811 else
6812 pkey->item_size = rpc_tid_size(type);
6813
6814 if ((type == TID_STRING || type == TID_LINK) && pkey->num_values == 1) {
6815 /* copy string up to NUL termination */
6816 mstrlcpy((char *) pheader + pkey->data, (const char*)data, data_size);
6817 } else {
6818 /* copy data */
6819 memcpy((char *) pheader + pkey->data, data, data_size);
6820 }
6821
6822 /* update time */
6823 pkey->last_written = ss_time();
6824
6825 return DB_SUCCESS;
6826}
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 7196 of file odb.cxx.

7197{
7198 if (rpc_is_remote())
7199 return rpc_call(RPC_DB_SET_LINK_DATA, hDB, hKey, data, buf_size, num_values, type);
7200
7201#ifdef LOCAL_ROUTINES
7202 {
7203 if (hDB > _database_entries || hDB <= 0) {
7204 cm_msg(MERROR, "db_set_data", "invalid database handle");
7205 return DB_INVALID_HANDLE;
7206 }
7207
7208 if (!_database[hDB - 1].attached) {
7209 cm_msg(MERROR, "db_set_data", "invalid database handle");
7210 return DB_INVALID_HANDLE;
7211 }
7212
7213 if (hKey < (int) sizeof(DATABASE_HEADER)) {
7214 cm_msg(MERROR, "db_set_data", "invalid key handle");
7215 return DB_INVALID_HANDLE;
7216 }
7217
7218 if (num_values == 0)
7219 return DB_INVALID_PARAM;
7220
7222 db_err_msg* msg = NULL;
7223
7224 DATABASE* pdb = &_database[hDB - 1];
7225 DATABASE_HEADER* pheader = pdb->database_header;
7226
7227 /* check if hKey argument is correct */
7228 if (!db_validate_hkey(pheader, hKey)) {
7230 return DB_INVALID_HANDLE;
7231 }
7232
7233 KEY* pkey = (KEY *) ((char *) pheader + hKey);
7234
7235 int status = db_check_set_data_locked(pheader, pkey, data, buf_size, num_values, type, "db_set_link_data", &msg);
7236
7237 if (status != DB_SUCCESS) {
7239 if (msg)
7240 db_flush_msg(&msg);
7241 return status;
7242 }
7243
7244 db_allow_write_locked(pdb, "db_set_link_data");
7245
7246 status = db_set_data_wlocked(pheader, pkey, data, buf_size, num_values, type, "db_set_link_data", &msg);
7247
7248 if (status != DB_SUCCESS) {
7250 if (msg)
7251 db_flush_msg(&msg);
7252 return status;
7253 }
7254
7255 db_notify_clients_locked(pdb, hKey, -1, TRUE, &msg);
7257 if (msg)
7258 db_flush_msg(&msg);
7259
7260 }
7261#endif /* LOCAL_ROUTINES */
7262
7263 return DB_SUCCESS;
7264}
#define RPC_DB_SET_LINK_DATA
Definition mrpc.h:93
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_link_data_index()

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

Same as db_set_data_index, but does not follow links.

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

Definition at line 7520 of file odb.cxx.

7521{
7522 if (rpc_is_remote())
7523 return rpc_call(RPC_DB_SET_LINK_DATA_INDEX, hDB, hKey, data, data_size, idx, type);
7524
7525#ifdef LOCAL_ROUTINES
7526 {
7527 if (hDB > _database_entries || hDB <= 0) {
7528 cm_msg(MERROR, "db_set_link_data_index", "invalid database handle");
7529 return DB_INVALID_HANDLE;
7530 }
7531
7532 if (!_database[hDB - 1].attached) {
7533 cm_msg(MERROR, "db_set_link_data_index", "invalid database handle");
7534 return DB_INVALID_HANDLE;
7535 }
7536
7537 if (hKey < (int) sizeof(DATABASE_HEADER)) {
7538 cm_msg(MERROR, "db_set_link_data_index", "invalid key handle");
7539 return DB_INVALID_HANDLE;
7540 }
7541
7543 db_err_msg* msg = NULL;
7544
7545 DATABASE* pdb = &_database[hDB - 1];
7546 DATABASE_HEADER* pheader = pdb->database_header;
7547
7548 /* check if hKey argument is correct */
7549 if (!db_validate_hkey(pheader, hKey)) {
7551 return DB_INVALID_HANDLE;
7552 }
7553
7554 KEY* pkey = (KEY *) ((char *) pheader + hKey);
7555
7556 int status = db_check_set_data_index_locked(pheader, pkey, idx, data, data_size, type, "db_set_link_data_index", &msg);
7557
7558 if (status != DB_SUCCESS) {
7560 if (msg)
7561 db_flush_msg(&msg);
7562 return status;
7563 }
7564
7565 db_allow_write_locked(pdb, "db_set_link_data_index");
7566
7567 status = db_set_data_index_wlocked(pheader, pkey, idx, data, data_size, type, "db_set_link_data_index", &msg);
7568
7569 if (status != DB_SUCCESS) {
7571 if (msg)
7572 db_flush_msg(&msg);
7573 return status;
7574 }
7575
7576 db_notify_clients_locked(pdb, hKey, idx, TRUE, &msg);
7578 if (msg)
7579 db_flush_msg(&msg);
7580
7581 }
7582#endif /* LOCAL_ROUTINES */
7583
7584 return DB_SUCCESS;
7585}
#define RPC_DB_SET_LINK_DATA_INDEX
Definition mrpc.h:94
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_lock_timeout()

INT db_set_lock_timeout ( HNDLE  hDB,
int  timeout_millisec 
)

Definition at line 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 7787 of file odb.cxx.

7812{
7813 if (rpc_is_remote())
7814 return rpc_call(RPC_DB_SET_MODE, hDB, hKey, mode, recurse);
7815
7816#ifdef LOCAL_ROUTINES
7817 {
7818 DATABASE_HEADER *pheader;
7819 BOOL locked = FALSE;
7820
7821 if (hDB > _database_entries || hDB <= 0) {
7822 cm_msg(MERROR, "db_set_mode", "invalid database handle");
7823 return DB_INVALID_HANDLE;
7824 }
7825
7826 if (!_database[hDB - 1].attached) {
7827 cm_msg(MERROR, "db_set_mode", "invalid database handle");
7828 return DB_INVALID_HANDLE;
7829 }
7830
7831 if (recurse < 2) {
7833 locked = TRUE;
7834 }
7835
7836 pheader = _database[hDB - 1].database_header;
7837
7838 db_err_msg* msg = NULL;
7839 int status = 0;
7840
7841 KEY *pkey = (KEY*)db_get_pkey(pheader, hKey, &status, "db_set_mode", &msg);
7842
7843 if (!pkey) {
7844 if (locked) {
7846 if (msg)
7847 db_flush_msg(&msg);
7848 return status;
7849 }
7850 }
7851
7852 db_allow_write_locked(&_database[hDB-1], "db_set_mode");
7853
7854 status = db_set_mode_wlocked(pheader, pkey, mode, recurse, &msg);
7855
7856 if (locked) {
7858 if (msg)
7859 db_flush_msg(&msg);
7860 }
7861
7862 return status;
7863 }
7864#endif /* LOCAL_ROUTINES */
7865
7866 return DB_SUCCESS;
7867}
#define RPC_DB_SET_MODE
Definition mrpc.h:68
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_mode_wlocked()

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

Definition at line 7739 of file odb.cxx.

7759{
7760 /* resolve links */
7761 if (pkey->type == TID_LINK) {
7762 int status;
7763 pkey = (KEY*)db_resolve_link_locked(pheader, pkey, &status, msg);
7764 if (!pkey) {
7765 return status;
7766 }
7767 }
7768
7769 if (pkey->type == TID_KEY && recurse) {
7770 // drop "const" from KEY* we are permitted to write to ODB!
7771 KEY* psubkey = (KEY*)db_enum_first_locked(pheader, pkey, msg);
7772 while (psubkey) {
7773 db_set_mode_wlocked(pheader, psubkey, mode, recurse+1, msg);
7774 psubkey = (KEY*)db_enum_next_locked(pheader, pkey, psubkey, msg);
7775 }
7776 }
7777
7778 /* now set mode */
7779 pkey->access_mode = mode;
7780
7781 return DB_SUCCESS;
7782}
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 7270 of file odb.cxx.

7290{
7291 if (rpc_is_remote())
7292 return rpc_call(RPC_DB_SET_NUM_VALUES, hDB, hKey, num_values);
7293
7294#ifdef LOCAL_ROUTINES
7295 {
7296 INT new_size;
7297
7298 if (hDB > _database_entries || hDB <= 0) {
7299 cm_msg(MERROR, "db_set_num_values", "invalid database handle");
7300 return DB_INVALID_HANDLE;
7301 }
7302
7303 if (!_database[hDB - 1].attached) {
7304 cm_msg(MERROR, "db_set_num_values", "invalid database handle");
7305 return DB_INVALID_HANDLE;
7306 }
7307
7308 if (hKey < (int) sizeof(DATABASE_HEADER)) {
7309 cm_msg(MERROR, "db_set_num_values", "invalid key handle");
7310 return DB_INVALID_HANDLE;
7311 }
7312
7313 if (num_values <= 0) {
7314 cm_msg(MERROR, "db_set_num_values", "invalid num_values %d", num_values);
7315 return DB_INVALID_PARAM;
7316 }
7317
7318 if (num_values == 0)
7319 return DB_INVALID_PARAM;
7320
7322 db_err_msg* msg = NULL;
7323
7324 DATABASE* pdb = &_database[hDB - 1];
7325 DATABASE_HEADER* pheader = pdb->database_header;
7326
7327 /* check if hKey argument is correct */
7328 if (!db_validate_hkey(pheader, hKey)) {
7330 return DB_INVALID_HANDLE;
7331 }
7332
7333 KEY* pkey = (KEY *) ((char *) pheader + hKey);
7334
7335 /* check for write access */
7336 if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
7338 return DB_NO_ACCESS;
7339 }
7340
7341 /* keys cannot contain data */
7342 if (pkey->type == TID_KEY) {
7344 cm_msg(MERROR, "db_set_num_values", "Key cannot contain data");
7345 return DB_TYPE_MISMATCH;
7346 }
7347
7348 if (pkey->total_size != pkey->item_size * pkey->num_values) {
7350 cm_msg(MERROR, "db_set_num_values", "Corrupted key");
7351 return DB_CORRUPTED;
7352 }
7353
7354 if (pkey->item_size == 0) {
7356 cm_msg(MERROR, "db_set_num_values", "Cannot resize array with item_size equal to zero");
7357 return DB_INVALID_PARAM;
7358 }
7359
7360 db_allow_write_locked(pdb, "db_set_num_values");
7361
7362 /* resize data size if necessary */
7363 if (pkey->num_values != num_values) {
7364 new_size = pkey->item_size * num_values;
7365
7366 pkey->data = (POINTER_T) realloc_data(pheader, (char *) pheader + pkey->data, pkey->total_size, new_size, "db_set_num_values");
7367
7368 if (pkey->data == 0) {
7369 pkey->total_size = 0;
7370 pkey->num_values = 0;
7371 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);
7373 if (msg)
7374 db_flush_msg(&msg);
7375 return DB_FULL;
7376 }
7377
7378 pkey->data -= (POINTER_T) pheader;
7379 pkey->total_size = new_size;
7380 pkey->num_values = num_values;
7381 }
7382
7383 /* update time */
7384 pkey->last_written = ss_time();
7385
7386 db_notify_clients_locked(pdb, hKey, -1, TRUE, &msg);
7388 if (msg)
7389 db_flush_msg(&msg);
7390
7391 }
7392#endif /* LOCAL_ROUTINES */
7393
7394 return DB_SUCCESS;
7395}
#define RPC_DB_SET_NUM_VALUES
Definition mrpc.h:88
Here is the call graph for this function:
Here is the caller graph for this function:

◆ db_set_record()

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

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

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

...
memset(&lazyst,0,size);
if (db_find_key(hDB, pLch->hKey, "Statistics",&hKeyst) == DB_SUCCESS)
else
cm_msg(MERROR,"task","record %s/statistics not found", pLch->name)
...
LAZY_STATISTICS lazyst
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 12067 of file odb.cxx.

12068{
12069 if (rpc_is_remote()) {
12070 align = ss_get_struct_align();
12071 return rpc_call(RPC_DB_SET_RECORD, hDB, hKey, data, buf_size, align);
12072 }
12073#ifdef LOCAL_ROUTINES
12074 {
12075 KEY key;
12076 INT convert_flags;
12077 INT total_size;
12078 void *pdata;
12079
12080 convert_flags = 0;
12081
12082 if (!align)
12083 align = ss_get_struct_align();
12084 else {
12085 /* only convert data if called remotely, as indicated by align != 0 */
12086 if (rpc_is_mserver()) {
12087 convert_flags = rpc_get_convert_flags();
12088 }
12089 }
12090
12091 /* check if key has subkeys */
12092 db_get_key(hDB, hKey, &key);
12093 if (key.type != TID_KEY) {
12094 /* copy single key */
12095 if (key.item_size * key.num_values != buf_size) {
12096 cm_msg(MERROR, "db_set_record", "struct size mismatch for \"%s\"", key.name);
12098 }
12099
12100 if (convert_flags) {
12101 if (key.num_values > 1)
12103 else
12104 rpc_convert_single(data, key.type, 0, convert_flags);
12105 }
12106
12108 return DB_SUCCESS;
12109 }
12110
12111 /* check record size */
12112 db_get_record_size(hDB, hKey, align, &total_size);
12113 if (total_size != buf_size) {
12114 cm_msg(MERROR, "db_set_record", "struct size mismatch for \"%s\"", key.name);
12116 }
12117
12118 /* set subkey data */
12119 pdata = data;
12120 total_size = 0;
12121
12123 db_err_msg* msg = NULL;
12124 DATABASE *pdb = &_database[hDB - 1];
12125 db_allow_write_locked(pdb, "db_set_record");
12126 db_recurse_record_tree_locked(pdb, hKey, &pdata, &total_size, align, NULL, TRUE, convert_flags, &msg);
12128 if (msg)
12129 db_flush_msg(&msg);
12130 }
12131#endif /* LOCAL_ROUTINES */
12132
12133 return DB_SUCCESS;
12134}
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:57
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 13785 of file odb.cxx.

13786{
13787 assert(s != NULL);
13788 int size = s->length() + 1; // 1 byte for final \0
13789 //printf("db_set_value_string: key_name [%s], string [%s], size %d\n", key_name, s->c_str(), size);
13790 return db_set_value(hDB, hKeyRoot, key_name, s->c_str(), size, 1, TID_STRING);
13791}
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 13941 of file odb.cxx.

13942{
13943 //printf("db_sor(%s)\n", root_path);
13944 assert(root_path != NULL);
13945#ifdef LOCAL_ROUTINES
13946 size_t root_path_len = strlen(root_path);
13947 MJsonNode* sor = MJsonNode::MakeArray();
13948
13949 /* lock database */
13951
13952 DATABASE *pdb = &_database[hDB - 1];
13953 DATABASE_HEADER *pheader = pdb->database_header;
13954
13955 /* list clients */
13956 for (int i = 0; i < pheader->max_client_index; i++) {
13957 DATABASE_CLIENT *pclient = &pheader->client[i];
13958 if (pclient->pid) {
13959 for (int j = 0; j < pclient->max_index; j++) {
13960 std::string path = db_get_path_locked(pheader, pclient->open_record[j].handle);
13961 if (path.length() < root_path_len)
13962 continue;
13963 if (strncmp(root_path, path.c_str(), root_path_len) != 0)
13964 continue;
13965 MJsonNode* c = MJsonNode::MakeObject();
13966 c->AddToObject("name", MJsonNode::MakeString(pclient->name));
13967 //c->AddToObject("handle", MJsonNode::MakeNumber(pclient->open_record[j].handle));
13968 c->AddToObject("access_mode", MJsonNode::MakeNumber(pclient->open_record[j].access_mode));
13969 c->AddToObject("flags", MJsonNode::MakeNumber(pclient->open_record[j].flags));
13970 c->AddToObject("path", MJsonNode::MakeString(path.c_str()));
13971 sor->AddToArray(c);
13972 }
13973 }
13974 }
13975
13977
13978 return sor;
13979#else
13980 return MJsonNode::MakeNull();
13981#endif
13982}
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 10612 of file odb.cxx.

10613{
10614 if (data_size == 0)
10615 sprintf(string, "<NULL>");
10616 else
10617 switch (type) {
10618 case TID_UINT8:
10619 sprintf(string, "%d", *(((BYTE *) data) + idx));
10620 break;
10621 case TID_INT8:
10622 sprintf(string, "%d", *(((char *) data) + idx));
10623 break;
10624 case TID_CHAR:
10625 sprintf(string, "%c", *(((char *) data) + idx));
10626 break;
10627 case TID_UINT16:
10628 sprintf(string, "%u", *(((WORD *) data) + idx));
10629 break;
10630 case TID_INT16:
10631 sprintf(string, "%d", *(((short *) data) + idx));
10632 break;
10633 case TID_UINT32:
10634 sprintf(string, "%u", *(((DWORD *) data) + idx));
10635 break;
10636 case TID_INT32:
10637 sprintf(string, "%d", *(((INT *) data) + idx));
10638 break;
10639 case TID_UINT64:
10640 sprintf(string, "%llu", *(((UINT64 *) data) + idx));
10641 break;
10642 case TID_INT64:
10643 sprintf(string, "%lld", *(((INT64 *) data) + idx));
10644 break;
10645 case TID_BOOL:
10646 sprintf(string, "%c", *(((BOOL *) data) + idx) ? 'y' : 'n');
10647 break;
10648 case TID_FLOAT:
10649 if (ss_isnan(*(((float *) data) + idx)))
10650 sprintf(string, "NAN");
10651 else
10652 sprintf(string, "%.7g", *(((float *) data) + idx));
10653 break;
10654 case TID_DOUBLE:
10655 if (ss_isnan(*(((double *) data) + idx)))
10656 sprintf(string, "NAN");
10657 else
10658 sprintf(string, "%.16lg", *(((double *) data) + idx));
10659 break;
10660 case TID_BITFIELD:
10661 sprintf(string, "%u", *(((DWORD *) data) + idx));
10662 break;
10663 case TID_STRING:
10664 case TID_LINK:
10665 mstrlcpy(string, ((char *) data) + data_size * idx, MAX_STRING_LENGTH);
10666 break;
10667 default:
10668 sprintf(string, "<unknown>");
10669 break;
10670 }
10671
10672 return DB_SUCCESS;
10673}
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 10856 of file odb.cxx.

10857{
10858 if (data_size == 0) {
10859 return "<NULL>";
10860 } else {
10861 char buf[256];
10862 switch (type) {
10863 case TID_UINT8:
10864 sprintf(buf, "%d", *(((BYTE *) data) + idx));
10865 return buf;
10866 case TID_INT8:
10867 sprintf(buf, "%d", *(((char *) data) + idx));
10868 return buf;
10869 case TID_CHAR:
10870 sprintf(buf, "%c", *(((char *) data) + idx));
10871 return buf;
10872 case TID_UINT16:
10873 sprintf(buf, "%u", *(((WORD *) data) + idx));
10874 return buf;
10875 case TID_INT16:
10876 sprintf(buf, "%d", *(((short *) data) + idx));
10877 return buf;
10878 case TID_UINT32:
10879 sprintf(buf, "%u", *(((DWORD *) data) + idx));
10880 return buf;
10881 case TID_INT32:
10882 sprintf(buf, "%d", *(((INT *) data) + idx));
10883 return buf;
10884 case TID_UINT64:
10885 sprintf(buf, "%llu", *(((UINT64 *) data) + idx));
10886 return buf;
10887 case TID_INT64:
10888 sprintf(buf, "%lld", *(((INT64 *) data) + idx));
10889 return buf;
10890 case TID_BOOL:
10891 sprintf(buf, "%c", *(((BOOL *) data) + idx) ? 'y' : 'n');
10892 return buf;
10893 case TID_FLOAT:
10894 if (ss_isnan(*(((float *) data) + idx))) {
10895 return "NAN";
10896 } else {
10897 sprintf(buf, "%.7g", *(((float *) data) + idx));
10898 return buf;
10899 }
10900 case TID_DOUBLE:
10901 if (ss_isnan(*(((double *) data) + idx))) {
10902 return "NAN";
10903 } else {
10904 sprintf(buf, "%.16lg", *(((double *) data) + idx));
10905 return buf;
10906 }
10907 case TID_BITFIELD:
10908 sprintf(buf, "%u", *(((DWORD *) data) + idx));
10909 return buf;
10910 case TID_STRING:
10911 case TID_LINK:
10912 return (((char *) data) + data_size * idx);
10913 default:
10914 return "<unknown>";
10915 }
10916 }
10917}
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 10688 of file odb.cxx.

10689{
10690 if (data_size == 0)
10691 sprintf(string, "<NULL>");
10692 else
10693 switch (type) {
10694 case TID_UINT8:
10695 sprintf(string, format, *(((BYTE *) data) + idx));
10696 break;
10697 case TID_INT8:
10698 sprintf(string, format, *(((char *) data) + idx));
10699 break;
10700 case TID_CHAR:
10701 sprintf(string, format, *(((char *) data) + idx));
10702 break;
10703 case TID_UINT16:
10704 sprintf(string, format, *(((WORD *) data) + idx));
10705 break;
10706 case TID_INT16:
10707 sprintf(string, format, *(((short *) data) + idx));
10708 break;
10709 case TID_UINT32:
10710 sprintf(string, format, *(((DWORD *) data) + idx));
10711 break;
10712 case TID_INT32:
10713 sprintf(string, format, *(((INT *) data) + idx));
10714 break;
10715 case TID_UINT64:
10716 sprintf(string, format, *(((UINT64 *) data) + idx));
10717 break;
10718 case TID_INT64:
10719 sprintf(string, format, *(((INT64 *) data) + idx));
10720 break;
10721 case TID_BOOL:
10722 sprintf(string, format, *(((BOOL *) data) + idx) ? 'y' : 'n');
10723 break;
10724 case TID_FLOAT:
10725 if (ss_isnan(*(((float *) data) + idx)))
10726 sprintf(string, "NAN");
10727 else
10728 sprintf(string, format, *(((float *) data) + idx));
10729 break;
10730 case TID_DOUBLE:
10731 if (ss_isnan(*(((double *) data) + idx)))
10732 sprintf(string, "NAN");
10733 else
10734 sprintf(string, format, *(((double *) data) + idx));
10735 break;
10736 case TID_BITFIELD:
10737 sprintf(string, format, *(((DWORD *) data) + idx));
10738 break;
10739 case TID_STRING:
10740 case TID_LINK:
10741 mstrlcpy(string, ((char *) data) + data_size * idx, MAX_STRING_LENGTH);
10742 break;
10743 default:
10744 sprintf(string, "<unknown>");
10745 break;
10746 }
10747
10748 return DB_SUCCESS;
10749}
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 10932 of file odb.cxx.

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

10773{
10774 if (data_size == 0)
10775 sprintf(string, "<NULL>");
10776 else
10777 switch (type) {
10778 case TID_UINT8:
10779 sprintf(string, "0x%X", *(((BYTE *) data) + idx));
10780 break;
10781 case TID_INT8:
10782 sprintf(string, "0x%X", *(((char *) data) + idx));
10783 break;
10784 case TID_CHAR:
10785 sprintf(string, "%c", *(((char *) data) + idx));
10786 break;
10787 case TID_UINT16:
10788 sprintf(string, "0x%X", *(((WORD *) data) + idx));
10789 break;
10790 case TID_INT16:
10791 sprintf(string, "0x%hX", *(((short *) data) + idx));
10792 break;
10793 case TID_UINT32:
10794 sprintf(string, "0x%X", *(((DWORD *) data) + idx));
10795 break;
10796 case TID_INT32:
10797 sprintf(string, "0x%X", *(((INT *) data) + idx));
10798 break;
10799 case TID_UINT64:
10800 sprintf(string, "0x%llX", *(((UINT64 *) data) + idx));
10801 break;
10802 case TID_INT64:
10803 sprintf(string, "0x%llX", *(((INT64 *) data) + idx));
10804 break;
10805 case TID_BOOL:
10806 sprintf(string, "%c", *(((BOOL *) data) + idx) ? 'y' : 'n');
10807 break;
10808 case TID_FLOAT:
10809 if (ss_isnan(*(((float *) data) + idx)))
10810 sprintf(string, "NAN");
10811 else
10812 sprintf(string, "%.7g", *(((float *) data) + idx));
10813 break;
10814 case TID_DOUBLE:
10815 if (ss_isnan(*(((double *) data) + idx)))
10816 sprintf(string, "NAN");
10817 else
10818 sprintf(string, "%.16lg", *(((double *) data) + idx));
10819 break;
10820 case TID_BITFIELD:
10821 sprintf(string, "0x%X", *(((DWORD *) data) + idx));
10822 break;
10823 case TID_STRING:
10824 case TID_LINK:
10825 sprintf(string, "%s", ((char *) data) + data_size * idx);
10826 break;
10827 default:
10828 sprintf(string, "<unknown>");
10829 break;
10830 }
10831
10832 return DB_SUCCESS;
10833}
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 10999 of file odb.cxx.

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

11103{
11104 DWORD value = 0;
11105 BOOL hex = FALSE;
11106
11107 if (data_str == NULL)
11108 return 0;
11109
11110 *data_size = rpc_tid_size(tid);
11111 if (strncmp(data_str, "0x", 2) == 0) {
11112 hex = TRUE;
11113 sscanf(data_str + 2, "%x", &value);
11114 }
11115
11116 switch (tid) {
11117 case TID_UINT8:
11118 case TID_INT8:
11119 if (hex)
11120 *((char *) data + i) = (char) value;
11121 else
11122 *((char *) data + i) = (char) atoi(data_str);
11123 break;
11124 case TID_CHAR:
11125 *((char *) data + i) = data_str[0];
11126 break;
11127 case TID_UINT16:
11128 if (hex)
11129 *((WORD *) data + i) = (WORD) value;
11130 else
11131 *((WORD *) data + i) = (WORD) atoi(data_str);
11132 break;
11133 case TID_INT16:
11134 if (hex)
11135 *((short int *) data + i) = (short int) value;
11136 else
11137 *((short int *) data + i) = (short int) atoi(data_str);
11138 break;
11139 case TID_UINT32:
11140 if (hex)
11141 value = strtoul(data_str, nullptr, 16);
11142 else
11143 value = strtoul(data_str, nullptr, 10);
11144
11145 *((DWORD *) data + i) = value;
11146 break;
11147 case TID_INT32:
11148 if (hex)
11149 value = strtol(data_str, nullptr, 16);
11150 else
11151 value = strtol(data_str, nullptr, 10);
11152
11153 *((INT *) data + i) = value;
11154 break;
11155 case TID_UINT64:
11156 if (hex)
11157 *((UINT64 *) data + i) = strtoull(data_str, nullptr, 16);
11158 else
11159 *((UINT64 *) data + i) = strtoull(data_str, nullptr, 10);
11160 break;
11161 case TID_INT64:
11162 if (hex)
11163 *((UINT64 *) data + i) = strtoll(data_str, nullptr, 16);
11164 else
11165 *((UINT64 *) data + i) = strtoll(data_str, nullptr, 10);
11166 break;
11167 case TID_BOOL:
11168 if (data_str[0] == 'y' || data_str[0] == 'Y' ||
11169 data_str[0] == 't' || data_str[0] == 'T' || atoi(data_str) > 0)
11170 *((BOOL *) data + i) = 1;
11171 else
11172 *((BOOL *) data + i) = 0;
11173 break;
11174 case TID_FLOAT:
11175 if (data_str[0] == 'n' || data_str[0] == 'N')
11176 *((float *) data + i) = (float) ss_nan();
11177 else
11178 *((float *) data + i) = (float) atof(data_str);
11179 break;
11180 case TID_DOUBLE:
11181 if (data_str[0] == 'n' || data_str[0] == 'N')
11182 *((double *) data + i) = ss_nan();
11183 else
11184 *((double *) data + i) = atof(data_str);
11185 break;
11186 case TID_BITFIELD:
11187 if (hex)
11188 value = strtoul(data_str, nullptr, 16);
11189 else
11190 value = strtoul(data_str, nullptr, 10);
11191
11192 *((DWORD *) data + i) = value;
11193 break;
11194 case TID_STRING:
11195 case TID_LINK:
11196 strcpy((char *) data, data_str);
11197 *data_size = strlen(data_str) + 1;
11198 break;
11199 }
11200
11201 return DB_SUCCESS;
11202}
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 13667 of file odb.cxx.

13668{
13669#ifdef LOCAL_ROUTINES
13670 {
13671 INT i;
13672
13673 for (i = 0; i < _watch_list_entries; i++)
13674 if (_watch_list[i].handle == hKey && _watch_list[i].hDB == hDB)
13675 break;
13676
13677 if (i == _watch_list_entries)
13678 return DB_INVALID_HANDLE;
13679
13680 /* remove record entry from database structure */
13682
13683 memset(&_watch_list[i], 0, sizeof(WATCH_LIST));
13684 }
13685#endif /* LOCAL_ROUTINES */
13686
13687 return DB_SUCCESS;
13688}
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 13697 of file odb.cxx.

13698{
13699 for (int i = _watch_list_entries-1; i >= 0 ; i--) {
13700 if ((_watch_list[i].hDB == 0) && (_watch_list[i].handle == 0)) {
13701 // empty or deleted watch list entry
13702 continue;
13703 }
13705 }
13706
13707 return DB_SUCCESS;
13708}
INT db_unwatch(HNDLE hDB, HNDLE hKey)
Definition odb.cxx:13667
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 13331 of file odb.cxx.

13332{
13333 INT i, size, status;
13334
13336
13337 /* check all record entries for matching key */
13338 for (i = 0; i < _record_list_entries; i++)
13339 if (_record_list[i].handle == hKeyRoot) {
13341
13342 /* get updated data if record not opened in write mode */
13343 if ((_record_list[i].access_mode & MODE_WRITE) == 0) {
13344 size = _record_list[i].buf_size;
13345 if (_record_list[i].data != NULL) {
13346 status = db_get_record(hDB, hKeyRoot, _record_list[i].data, &size, 0); // db_open_record() update
13347 //printf("db_open_record update status %d, size %d %d\n", status, _record_list[i].buf_size, size);
13348 }
13349
13350 /* call dispatcher if requested */
13351 if (_record_list[i].dispatcher)
13353 }
13354 }
13355
13356 /* check all watch entries for matching key */
13357 for (i = 0; i < _watch_list_entries; i++)
13358 if (_watch_list[i].handle == hKeyRoot) {
13360
13361 /* call dispatcher if requested */
13362 if (_watch_list[i].dispatcher)
13364 }
13365
13366 return status;
13367}
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 13378 of file odb.cxx.

13379{
13380 char buffer[32];
13381
13382 int convert_flags = rpc_get_convert_flags();
13383
13384 NET_COMMAND* nc = (NET_COMMAND *) buffer;
13385
13387 nc->header.param_size = 4 * sizeof(INT);
13388 *((INT *) nc->param) = hDB;
13389 *((INT *) nc->param + 1) = hKeyRoot;
13390 *((INT *) nc->param + 2) = hKey;
13391 *((INT *) nc->param + 3) = index;
13392
13393 if (convert_flags) {
13396 rpc_convert_single(&nc->param[0], TID_UINT32, RPC_OUTGOING, convert_flags);
13397 rpc_convert_single(&nc->param[4], TID_UINT32, RPC_OUTGOING, convert_flags);
13398 rpc_convert_single(&nc->param[8], TID_UINT32, RPC_OUTGOING, convert_flags);
13399 rpc_convert_single(&nc->param[12], TID_UINT32, RPC_OUTGOING, convert_flags);
13400 }
13401
13402 /* send the update notification to the client */
13403 send_tcp(client_socket, buffer, sizeof(NET_COMMAND_HEADER) + 4 * sizeof(INT), 0);
13404
13405 return DB_SUCCESS;
13406}
#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 13592 of file odb.cxx.

13593{
13594 INT idx, status;
13595 KEY key;
13596
13597 /* check for valid key */
13598 assert(hKey);
13599
13600 /* allocate new space for the local record list */
13601 if (_watch_list_entries == 0) {
13602 _watch_list = (WATCH_LIST *) malloc(sizeof(WATCH_LIST));
13603 assert(_watch_list != NULL);
13604 memset(_watch_list, 0, sizeof(WATCH_LIST));
13605 if (_watch_list == NULL) {
13606 cm_msg(MERROR, "db_watch", "not enough memory");
13607 return DB_NO_MEMORY;
13608 }
13609
13611 idx = 0;
13612 } else {
13613 /* check for a deleted entry */
13614 for (idx = 0; idx < _watch_list_entries; idx++)
13615 if (!_watch_list[idx].handle)
13616 break;
13617
13618 /* if not found, create new one */
13619 if (idx == _watch_list_entries) {
13620 _watch_list = (WATCH_LIST *) realloc(_watch_list, sizeof(WATCH_LIST) * (_watch_list_entries + 1));
13621 if (_watch_list == NULL) {
13622 cm_msg(MERROR, "db_watch", "not enough memory");
13623 return DB_NO_MEMORY;
13624 }
13625
13626 memset(&_watch_list[_watch_list_entries], 0, sizeof(WATCH_LIST));
13627
13629 }
13630 }
13631
13632 /* check key */
13634 if (status != DB_SUCCESS) {
13636 std::string path = db_get_path(hDB, hKey);
13637 cm_msg(MERROR, "db_watch", "cannot get key \"%s\"", path.c_str());
13638 return DB_NO_MEMORY;
13639 }
13640
13641 /* check for read access */
13642 if (!(key.access_mode & MODE_READ)) {
13644 std::string path = db_get_path(hDB, hKey);
13645 cm_msg(MERROR, "db_watch", "cannot get key \"%s\"", path.c_str());
13646 return DB_NO_ACCESS;
13647 }
13648
13649 /* initialize record list */
13650 _watch_list[idx].handle = hKey;
13651 _watch_list[idx].hDB = hDB;
13652 _watch_list[idx].dispatcher = dispatcher;
13653 _watch_list[idx].info = info;
13654
13655 /* add record entry in database structure */
13657}
#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 9397 of file odb.cxx.

9398{
9399 // sprintf "%.2e" can result in strings like "1,23e6" if
9400 // the user's locale has a comma for the decimal spearator.
9401 // However the JSON RFC requires a dot for the decimal.
9402 // This approach of "sprintf-then-replace" is much safer than
9403 // changing the user's locale, and much faster than the C++
9404 // approach of using a stringstream that we "imbue" with a C locale.
9405 char* comma = strchr(str, ',');
9406
9407 if (comma != nullptr) {
9408 *comma = '.';
9409 }
9410}
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 9297 of file odb.cxx.

9298{
9299 int len, remain, xlevel;
9300
9301 len = strlen(s);
9302 remain = *buffer_size - *buffer_end;
9303 assert(remain >= 0);
9304
9305 xlevel = 2*level;
9306
9307 while (10 + xlevel + 3*len > remain) {
9308 // reallocate the buffer
9309 int new_buffer_size = 2*(*buffer_size);
9310 if (new_buffer_size < 4*1024)
9311 new_buffer_size = 4*1024;
9312 //printf("reallocate: len %d, size %d, remain %d, allocate %d\n", len, *buffer_size, remain, new_buffer_size);
9313 assert(new_buffer_size > *buffer_size);
9314 *buffer = (char *)realloc(*buffer, new_buffer_size);
9315 assert(*buffer);
9316 *buffer_size = new_buffer_size;
9317 remain = *buffer_size - *buffer_end;
9318 assert(remain >= 0);
9319 }
9320
9321 if (xlevel) {
9322 int i;
9323 for (i=0; i<xlevel; i++)
9324 (*buffer)[(*buffer_end)++] = ' ';
9325 }
9326
9327 if (!quoted) {
9328 memcpy(*buffer + *buffer_end, s, len);
9329 *buffer_end += len;
9330 (*buffer)[*buffer_end] = 0; // NUL-terminate the buffer
9331 return;
9332 }
9333
9334 char *bufptr = *buffer;
9335 int bufend = *buffer_end;
9336
9337 bufptr[bufend++] = '"';
9338
9339 while (*s) {
9340 switch (*s) {
9341 case '\"':
9342 bufptr[bufend++] = '\\';
9343 bufptr[bufend++] = '\"';
9344 s++;
9345 break;
9346 case '\\':
9347 bufptr[bufend++] = '\\';
9348 bufptr[bufend++] = '\\';
9349 s++;
9350 break;
9351#if 0
9352 case '/':
9353 bufptr[bufend++] = '\\';
9354 bufptr[bufend++] = '/';
9355 s++;
9356 break;
9357#endif
9358 case '\b':
9359 bufptr[bufend++] = '\\';
9360 bufptr[bufend++] = 'b';
9361 s++;
9362 break;
9363 case '\f':
9364 bufptr[bufend++] = '\\';
9365 bufptr[bufend++] = 'f';
9366 s++;
9367 break;
9368 case '\n':
9369 bufptr[bufend++] = '\\';
9370 bufptr[bufend++] = 'n';
9371 s++;
9372 break;
9373 case '\r':
9374 bufptr[bufend++] = '\\';
9375 bufptr[bufend++] = 'r';
9376 s++;
9377 break;
9378 case '\t':
9379 bufptr[bufend++] = '\\';
9380 bufptr[bufend++] = 't';
9381 s++;
9382 break;
9383 default:
9384 bufptr[bufend++] = *s++;
9385 }
9386 }
9387
9388 bufptr[bufend++] = '"';
9389 bufptr[bufend] = 0; // NUL-terminate the buffer
9390
9391 *buffer_end = bufend;
9392
9393 remain = *buffer_size - *buffer_end;
9394 assert(remain > 0);
9395}
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 10152 of file odb.cxx.

10153{
10154 int status;
10155 KEY key;
10156
10158 if (status != DB_SUCCESS)
10159 return status;
10160
10161 if (key.type == TID_KEY) {
10162
10163 json_write(buffer, buffer_size, buffer_end, 0, "{", 0);
10164
10165 status = json_write_bare_subdir(hDB, hKey, buffer, buffer_size, buffer_end, level+1, flags, timestamp);
10166 if (status != DB_SUCCESS)
10167 return status;
10168
10169 json_write(buffer, buffer_size, buffer_end, 0, "\n", 0);
10170 json_write(buffer, buffer_size, buffer_end, level, "}", 0);
10171
10172 } else if (must_be_subdir) {
10173 json_write(buffer, buffer_size, buffer_end, 0, "{", 0);
10174 status = json_write_bare_key(hDB, hKey, key, buffer, buffer_size, buffer_end, level+1, flags, timestamp, false);
10175 if (status != DB_SUCCESS)
10176 return status;
10177 json_write(buffer, buffer_size, buffer_end, 0, "\n", 0);
10178 json_write(buffer, buffer_size, buffer_end, level, "}", 0);
10179 } else {
10180 status = db_copy_json_array(hDB, hKey, buffer, buffer_size, buffer_end);
10181
10182 if (status != DB_SUCCESS)
10183 return status;
10184 }
10185
10186 return DB_SUCCESS;
10187}
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:10020
INT db_copy_json_array(HNDLE hDB, HNDLE hKey, char **buffer, int *buffer_size, int *buffer_end)
Definition odb.cxx:9920
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 10020 of file odb.cxx.

10021{
10022 int status;
10023 char link_buf[MAX_ODB_PATH]; // link_path points to link_buf
10024 char* link_path = NULL;
10025
10026 HNDLE hLinkTarget = hLink;
10027
10028 if (link.type == TID_LINK) {
10029 int size = sizeof(link_buf);
10030 status = db_get_link_data(hDB, hLink, link_buf, &size, TID_LINK);
10031 if (status != DB_SUCCESS)
10032 return status;
10033
10034 //printf("link size %d, len %d, data [%s]\n", size, (int)strlen(link_buf), link_buf);
10035
10036 if ((size > 0) && (strlen(link_buf) > 0)) {
10037 link_path = link_buf;
10038
10039 // resolve the link, unless it is a link to an array element
10040 if ((flags & JSFLAG_FOLLOW_LINKS) && strchr(link_path, '[') == NULL) {
10041 status = db_find_key(hDB, 0, link_path, &hLinkTarget);
10042 if (status != DB_SUCCESS) {
10043 // dangling link to nowhere
10044 hLinkTarget = hLink;
10045 }
10046 }
10047 }
10048 }
10049
10050 KEY link_target;
10051 status = db_get_key(hDB, hLinkTarget, &link_target);
10052 if (status != DB_SUCCESS)
10053 return status;
10054
10055 if (flags & JSFLAG_OMIT_OLD) {
10056 if (link_target.last_written) {
10057 if (link_target.last_written < timestamp) {
10058 // omit old data
10059 return DB_SUCCESS;
10060 }
10061 }
10062 }
10063
10064 if (need_comma) {
10065 json_write(buffer, buffer_size, buffer_end, 0, ",\n", 0);
10066 } else {
10067 json_write(buffer, buffer_size, buffer_end, 0, "\n", 0);
10068 }
10069
10070 char link_name[MAX_ODB_PATH];
10071
10072 mstrlcpy(link_name, link.name, sizeof(link_name));
10073
10074 if (flags & JSFLAG_LOWERCASE) {
10075 for (int i=0; (i<(int)sizeof(link.name)) && link.name[i]; i++)
10076 link_name[i] = tolower(link.name[i]);
10077 }
10078
10079 if ((flags & JSFLAG_LOWERCASE) && !(flags & JSFLAG_OMIT_NAMES)) {
10080 char buf[MAX_ODB_PATH];
10081 mstrlcpy(buf, link_name, sizeof(buf));
10082 mstrlcat(buf, "/name", sizeof(buf));
10083 json_write(buffer, buffer_size, buffer_end, level, buf, 1);
10084 json_write(buffer, buffer_size, buffer_end, 0, " : " , 0);
10085 json_write(buffer, buffer_size, buffer_end, 0, link.name, 1);
10086 json_write(buffer, buffer_size, buffer_end, 0, ",\n", 0);
10087 }
10088
10089 if (link.type != TID_KEY && (flags & JSFLAG_SAVE_KEYS)) {
10090 char buf[MAX_ODB_PATH];
10091 mstrlcpy(buf, link_name, sizeof(buf));
10092 mstrlcat(buf, "/key", sizeof(buf));
10093 json_write(buffer, buffer_size, buffer_end, level, buf, 1);
10094 json_write(buffer, buffer_size, buffer_end, 0, " : " , 0);
10095 json_write_key(hDB, hLink, &link_target, link_path, buffer, buffer_size, buffer_end);
10096 json_write(buffer, buffer_size, buffer_end, 0, ",\n", 0);
10097 } else if ((link_target.type != TID_KEY) && !(flags & JSFLAG_OMIT_LAST_WRITTEN)) {
10098 char buf[MAX_ODB_PATH];
10099 mstrlcpy(buf, link_name, sizeof(buf));
10100 mstrlcat(buf, "/last_written", sizeof(buf));
10101 json_write(buffer, buffer_size, buffer_end, level, buf, 1);
10102 json_write(buffer, buffer_size, buffer_end, 0, " : " , 0);
10103 sprintf(buf, "%d", link_target.last_written);
10104 json_write(buffer, buffer_size, buffer_end, 0, buf, 0);
10105 json_write(buffer, buffer_size, buffer_end, 0, ",\n", 0);
10106 }
10107
10108 json_write(buffer, buffer_size, buffer_end, level, link_name, 1);
10109 json_write(buffer, buffer_size, buffer_end, 0, " : " , 0);
10110
10111 if (link_target.type == TID_KEY && !(flags & JSFLAG_RECURSE)) {
10112 json_write(buffer, buffer_size, buffer_end, 0, "{ }" , 0);
10113 } else {
10114 status = json_write_anything(hDB, hLinkTarget, buffer, buffer_size, buffer_end, level, 0, flags, timestamp);
10115 if (status != DB_SUCCESS)
10116 return status;
10117 }
10118
10119 return DB_SUCCESS;
10120}
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:9529
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 10122 of file odb.cxx.

10123{
10124 if (level > MAX_ODB_PATH) {
10125 cm_msg(MERROR, "json_write_bare_subdir", "Max ODB subdirectory nesting level exceeded %d at \"%s\"", level, db_get_path(hDB, hKey).c_str());
10126 return DB_TRUNCATED;
10127 }
10128
10129 for (int i=0; ; i++) {
10130 int status;
10131
10132 HNDLE hLink;
10133 status = db_enum_link(hDB, hKey, i, &hLink);
10134 if (status != DB_SUCCESS && !hLink)
10135 break;
10136
10137 KEY link;
10138 status = db_get_link(hDB, hLink, &link);
10139 if (status != DB_SUCCESS)
10140 return status;
10141
10142 bool need_comma = (i!=0);
10143
10144 status = json_write_bare_key(hDB, hLink, link, buffer, buffer_size, buffer_end, level, flags, timestamp, need_comma);
10145 if (status != DB_SUCCESS)
10146 return status;
10147 }
10148
10149 return DB_SUCCESS;
10150}
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 9412 of file odb.cxx.

9413{
9414 char str[256];
9415 switch (key->type) {
9416 case TID_UINT8:
9417 sprintf(str, "%u", *(unsigned char*)p);
9418 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9419 break;
9420 case TID_INT8:
9421 sprintf(str, "%d", *(char*)p);
9422 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9423 break;
9424 case TID_CHAR:
9425 sprintf(str, "%c", *(char*)p);
9426 json_write(buffer, buffer_size, buffer_end, 0, str, 1);
9427 break;
9428 case TID_UINT16:
9429 sprintf(str, "\"0x%04x\"", *(WORD*)p);
9430 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9431 break;
9432 case TID_INT16:
9433 sprintf(str, "%d", *(short*)p);
9434 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9435 break;
9436 case TID_UINT32:
9437 sprintf(str, "\"0x%08x\"", *(DWORD*)p);
9438 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9439 break;
9440 case TID_INT32:
9441 sprintf(str, "%d", *(int*)p);
9442 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9443 break;
9444 case TID_UINT64:
9445 // encode as hex string
9446 sprintf(str, "\"0x%016llx\"", *(UINT64*)p);
9447 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9448 break;
9449 case TID_INT64:
9450 // encode as decimal string
9451 sprintf(str, "\"%lld\"", *(INT64*)p);
9452 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9453 break;
9454 case TID_BOOL:
9455 if (*(int*)p)
9456 json_write(buffer, buffer_size, buffer_end, 0, "true", 0);
9457 else
9458 json_write(buffer, buffer_size, buffer_end, 0, "false", 0);
9459 break;
9460 case TID_FLOAT: {
9461 float flt = (*(float*)p);
9462 if (isnan(flt))
9463 json_write(buffer, buffer_size, buffer_end, 0, "\"NaN\"", 0);
9464 else if (isinf(flt)) {
9465 if (flt > 0)
9466 json_write(buffer, buffer_size, buffer_end, 0, "\"Infinity\"", 0);
9467 else
9468 json_write(buffer, buffer_size, buffer_end, 0, "\"-Infinity\"", 0);
9469 } else if (flt == 0)
9470 json_write(buffer, buffer_size, buffer_end, 0, "0", 0);
9471 else if (flt == (int)flt) {
9472 sprintf(str, "%.0f", flt);
9474 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9475 } else {
9476 sprintf(str, "%.7e", flt);
9478 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9479 }
9480 break;
9481 }
9482 case TID_DOUBLE: {
9483 double dbl = (*(double*)p);
9484 if (isnan(dbl))
9485 json_write(buffer, buffer_size, buffer_end, 0, "\"NaN\"", 0);
9486 else if (isinf(dbl)) {
9487 if (dbl > 0)
9488 json_write(buffer, buffer_size, buffer_end, 0, "\"Infinity\"", 0);
9489 else
9490 json_write(buffer, buffer_size, buffer_end, 0, "\"-Infinity\"", 0);
9491 } else if (dbl == 0)
9492 json_write(buffer, buffer_size, buffer_end, 0, "0", 0);
9493 else if (dbl == (int)dbl) {
9494 sprintf(str, "%.0f", dbl);
9496 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9497 } else {
9498 sprintf(str, "%.16e", dbl);
9500 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9501 }
9502 break;
9503 }
9504 case TID_BITFIELD:
9505 json_write(buffer, buffer_size, buffer_end, 0, "(TID_BITFIELD value)", 1);
9506 break;
9507 case TID_STRING:
9508 // data is already NUL terminated // p[key.item_size-1] = 0; // make sure string is NUL terminated!
9509 json_write(buffer, buffer_size, buffer_end, 0, p, 1);
9510 break;
9511 case TID_ARRAY:
9512 json_write(buffer, buffer_size, buffer_end, 0, "(TID_ARRAY value)", 1);
9513 break;
9514 case TID_STRUCT:
9515 json_write(buffer, buffer_size, buffer_end, 0, "(TID_STRUCT value)", 1);
9516 break;
9517 case TID_KEY:
9518 json_write(buffer, buffer_size, buffer_end, 0, "{ }", 0);
9519 break;
9520 case TID_LINK:
9521 // data is already NUL terminated // p[key.item_size-1] = 0; // make sure string is NUL terminated!
9522 json_write(buffer, buffer_size, buffer_end, 0, p, 1);
9523 break;
9524 default:
9525 json_write(buffer, buffer_size, buffer_end, 0, "(TID_UNKNOWN value)", 1);
9526 }
9527}
static void json_ensure_decimal_dot(char *str)
Definition odb.cxx:9397
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 9529 of file odb.cxx.

9530{
9531 char str[256]; // not used to store anything long, only numeric values like: "item_size: 100"
9532
9533 json_write(buffer, buffer_size, buffer_end, 0, "{ ", 0);
9534
9535 sprintf(str, "\"type\" : %d", key->type);
9536 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9537
9538 if (link_path) {
9539 json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9540 json_write(buffer, buffer_size, buffer_end, 0, "link", 1);
9541 json_write(buffer, buffer_size, buffer_end, 0, ": ", 0);
9542 json_write(buffer, buffer_size, buffer_end, 0, link_path, 1);
9543 }
9544
9545 if (key->num_values > 1) {
9546 json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9547
9548 sprintf(str, "\"num_values\" : %d", key->num_values);
9549 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9550 }
9551
9552 if (key->type == TID_STRING) {
9553 json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9554
9555 sprintf(str, "\"item_size\" : %d", key->item_size);
9556 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9557 }
9558
9559 if (key->notify_count > 0) {
9560 json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9561
9562 sprintf(str, "\"notify_count\" : %d", key->notify_count);
9563 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9564 }
9565
9566 json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9567
9568 sprintf(str, "\"access_mode\" : %d", key->access_mode);
9569 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9570
9571 json_write(buffer, buffer_size, buffer_end, 0, ", ", 0);
9572
9573 sprintf(str, "\"last_written\" : %d", key->last_written);
9574 json_write(buffer, buffer_size, buffer_end, 0, str, 0);
9575
9576 json_write(buffer, buffer_size, buffer_end, 0, " ", 0);
9577
9578 json_write(buffer, buffer_size, buffer_end, 0, "}", 0);
9579}
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 12437 of file odb.cxx.

12438{
12439 char full_name[MAX_ODB_PATH];
12440 INT status, size;
12441 HNDLE hKeyInit;
12442 KEY initkey, key;
12443
12444 /* avoid compiler warnings */
12445 status = level;
12446
12447 /* compose name of init key */
12448 std::string s = db_get_path(hDB, hKey);
12449 mstrlcpy(full_name, s.c_str(), sizeof(full_name));
12450 *strchr(full_name, 'O') = 'I';
12451
12452 /* if key in init record found, copy original data to init data */
12453 status = db_find_key(hDB, 0, full_name, &hKeyInit);
12454 if (status == DB_SUCCESS) {
12455 status = db_get_key(hDB, hKeyInit, &initkey);
12456 if (status != DB_SUCCESS) {
12457 cm_msg(MERROR, "merge_records", "merge_record error at \'%s\', db_get_key() status %d", full_name, status);
12458 return;
12459 }
12461 if (status != DB_SUCCESS) {
12462 cm_msg(MERROR, "merge_records", "merge_record error at \'%s\', second db_get_key() status %d", full_name, status);
12463 return;
12464 }
12465
12466 if (initkey.type != TID_KEY && initkey.type == key.type) {
12467 char* allocbuffer = NULL;
12468 char stackbuffer[10000];
12469 char* buffer = stackbuffer;
12470 size = sizeof(stackbuffer);
12471 while (1) {
12472 /* copy data from original key to new key */
12473 status = db_get_data(hDB, hKey, buffer, &size, initkey.type);
12474 if (status == DB_SUCCESS) {
12475 status = db_set_data(hDB, hKeyInit, buffer, initkey.total_size, initkey.num_values, initkey.type);
12476 if (status != DB_SUCCESS) {
12477 cm_msg(MERROR, "merge_records", "merge_record error at \'%s\', db_set_data() status %d", full_name, status);
12478 return;
12479 }
12480 break;
12481 }
12482 if (status == DB_TRUNCATED) {
12483 size *= 2;
12484 allocbuffer = (char *)realloc(allocbuffer, size);
12485 assert(allocbuffer != NULL);
12486 buffer = allocbuffer;
12487 continue;
12488 }
12489 cm_msg(MERROR, "merge_records", "aborting on unexpected failure of db_get_data(%s), status %d", full_name, status);
12490 abort();
12491 }
12492 if (allocbuffer)
12493 free(allocbuffer);
12494 }
12495 } else if (status == DB_NO_KEY) {
12496 /* do nothing */
12497 } else if (status == DB_INVALID_LINK) {
12498 status = db_find_link(hDB, 0, full_name, &hKeyInit);
12499 if (status == DB_SUCCESS) {
12500 size = sizeof(full_name);
12501 status = db_get_data(hDB, hKeyInit, full_name, &size, TID_LINK);
12502 }
12503 cm_msg(MERROR, "merge_records", "Invalid link \"%s\"", full_name);
12504 } else {
12505 cm_msg(MERROR, "merge_records", "aborting on unexpected failure of db_find_key(%s), status %d", full_name, status);
12506 abort();
12507 }
12508}
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 8862 of file odb.cxx.

8870{
8871 if (*str >= '0' && *str <= '9')
8872 *str = '_';
8873
8874 while (*str) {
8875 if (!(*str >= 'a' && *str <= 'z') && !(*str >= 'A' && *str <= 'Z') && !(*str >= '0' && *str <= '9'))
8876 *str = '_';
8877 *str = (char) tolower(*str);
8878 str++;
8879 }
8880}
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 9068 of file odb.cxx.

9069{
9070 int i;
9071 char *dst, *p;
9072
9073 dst = (char *) malloc(size);
9074 if (dst == NULL)
9075 return;
9076
9077 *dst = 0;
9078 for (i = 0; i < (int) strlen(src); i++) {
9079 switch (src[i]) {
9080 case '<':
9081 mstrlcat(dst, "&lt;", size);
9082 break;
9083 case '>':
9084 mstrlcat(dst, "&gt;", size);
9085 break;
9086 case '&':
9087 mstrlcat(dst, "&amp;", size);
9088 break;
9089 case '\"':
9090 mstrlcat(dst, "&quot;", size);
9091 break;
9092 case '\'':
9093 mstrlcat(dst, "&apos;", size);
9094 break;
9095 default:
9096 if ((int) strlen(dst) >= size) {
9097 free(dst);
9098 return;
9099 }
9100 p = dst + strlen(dst);
9101 *p = src[i];
9102 *(p + 1) = 0;
9103 }
9104 }
9105
9106 mstrlcpy(src, dst, size);
9107}

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 12510 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.