Midas ODB Functions (db_xxx)
[The odb.c]


Functions

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_lock_database (HNDLE hDB)
INT db_unlock_database (HNDLE hDB)
INT db_get_lock_cnt (HNDLE hDB)
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)
INT db_create_key (HNDLE hDB, HNDLE hKey, const char *key_name, DWORD type)
INT db_create_link (HNDLE hDB, HNDLE hKey, const char *link_name, const char *destination)
INT db_delete_key1 (HNDLE hDB, HNDLE hKey, INT level, BOOL follow_links)
INT db_delete_key (HNDLE hDB, HNDLE hKey, BOOL follow_links)
INT db_find_key (HNDLE hDB, HNDLE hKey, const char *key_name, HNDLE *subhKey)
INT db_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_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_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_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_link_data (HNDLE hDB, HNDLE hKey, const void *data, INT buf_size, INT num_values, DWORD type)
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_load (HNDLE hDB, HNDLE hKeyRoot, const char *filename, BOOL bRemote)
INT db_copy (HNDLE hDB, HNDLE hKey, char *buffer, INT *buffer_size, char *path)
INT db_paste (HNDLE hDB, HNDLE hKeyRoot, const char *buffer)
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)
INT db_save (HNDLE hDB, HNDLE hKey, const char *filename, BOOL bRemote)
void xml_encode (char *src, int size)
INT db_save_xml_key (HNDLE hDB, HNDLE hKey, INT level, MXML_WRITER *writer)
INT db_save_xml (HNDLE hDB, HNDLE hKey, const char *filename)
INT db_save_struct (HNDLE hDB, HNDLE hKey, const char *file_name, const char *struct_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_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_set_record (HNDLE hDB, HNDLE hKey, void *data, INT buf_size, INT align)
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_close_record (HNDLE hDB, HNDLE hKey)
INT db_close_all_records ()
INT db_update_record (INT hDB, INT hKey, int s)
INT db_send_changed_records ()


Function Documentation

INT 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:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Handle for key where search starts, zero for root.
keyname Name of key to search, can contain directories.
rec_str ASCII representation of ODB record in the format
correct If TRUE, correct ODB record if necessary
Returns:
DB_SUCCESS, DB_INVALID_HANDLE, DB_NO_KEY, DB_STRUCT_MISMATCH

Definition at line 8158 of file odb.c.

Referenced by al_check(), al_trigger_alarm(), cm_connect_experiment1(), init_module_parameters(), logger_init(), main(), mana_init(), register_equipment(), register_requests(), rpc_server_dispatch(), show_custom_gif(), show_status_page(), and tr_start().

08159 {
08160    char line[MAX_STRING_LENGTH];
08161    char title[MAX_STRING_LENGTH];
08162    char key_name[MAX_STRING_LENGTH];
08163    char info_str[MAX_STRING_LENGTH + 50];
08164    char *pc;
08165    const char *pold, *rec_str_orig;
08166    DWORD tid;
08167    INT i, j, n_data, string_length, status;
08168    HNDLE hKeyRoot, hKeyTest;
08169    KEY key;
08170    BOOL multi_line;
08171 
08172    if (rpc_is_remote())
08173       return rpc_call(RPC_DB_CHECK_RECORD, hDB, hKey, keyname, rec_str, correct);
08174 
08175    /* check if record exists */
08176    status = db_find_key(hDB, hKey, keyname, &hKeyRoot);
08177 
08178    /* create record if not */
08179    if (status == DB_NO_KEY) {
08180       if (correct)
08181          return db_create_record(hDB, hKey, keyname, rec_str);
08182       return DB_NO_KEY;
08183    }
08184 
08185    assert(hKeyRoot);
08186 
08187    title[0] = 0;
08188    multi_line = FALSE;
08189    rec_str_orig = rec_str;
08190 
08191    db_get_key(hDB, hKeyRoot, &key);
08192    if (key.type == TID_KEY)
08193       /* get next subkey which is not of type TID_KEY */
08194       db_get_next_link(hDB, hKeyRoot, &hKeyTest);
08195    else
08196       /* test root key itself */
08197       hKeyTest = hKeyRoot;
08198 
08199    if (hKeyTest == 0 && *rec_str != 0) {
08200       if (correct)
08201          return db_create_record(hDB, hKey, keyname, rec_str_orig);
08202 
08203       return DB_STRUCT_MISMATCH;
08204    }
08205 
08206    do {
08207       if (*rec_str == 0)
08208          break;
08209 
08210       for (i = 0; *rec_str != '\n' && *rec_str && i < MAX_STRING_LENGTH; i++)
08211          line[i] = *rec_str++;
08212 
08213       if (i == MAX_STRING_LENGTH) {
08214          cm_msg(MERROR, "db_check_record", "line too long");
08215          return DB_TRUNCATED;
08216       }
08217 
08218       line[i] = 0;
08219       if (*rec_str == '\n')
08220          rec_str++;
08221 
08222       /* check if it is a section title */
08223       if (line[0] == '[') {
08224          /* extract title and append '/' */
08225          strcpy(title, line + 1);
08226          if (strchr(title, ']'))
08227             *strchr(title, ']') = 0;
08228          if (title[0] && title[strlen(title) - 1] != '/')
08229             strcat(title, "/");
08230       } else {
08231          /* valid data line if it includes '=' and no ';' */
08232          if (strchr(line, '=') && line[0] != ';') {
08233             /* copy type info and data */
08234             pc = strchr(line, '=') + 1;
08235             while (*pc == ' ')
08236                pc++;
08237             strcpy(info_str, pc);
08238 
08239             /* extract key name */
08240             *strchr(line, '=') = 0;
08241 
08242             pc = &line[strlen(line) - 1];
08243             while (*pc == ' ')
08244                *pc-- = 0;
08245 
08246             strlcpy(key_name, line, sizeof(key_name));
08247 
08248             /* evaluate type info */
08249             strcpy(line, info_str);
08250             if (strchr(line, ' '))
08251                *strchr(line, ' ') = 0;
08252 
08253             n_data = 1;
08254             if (strchr(line, '[')) {
08255                n_data = atol(strchr(line, '[') + 1);
08256                *strchr(line, '[') = 0;
08257             }
08258 
08259             for (tid = 0; tid < TID_LAST; tid++)
08260                if (strcmp(tid_name[tid], line) == 0)
08261                   break;
08262 
08263             string_length = 0;
08264 
08265             if (tid == TID_LAST)
08266                cm_msg(MERROR, "db_check_record", "found unknown data type \"%s\" in ODB file", line);
08267             else {
08268                /* skip type info */
08269                pc = info_str;
08270                while (*pc != ' ' && *pc)
08271                   pc++;
08272                while ((*pc == ' ' || *pc == ':') && *pc)
08273                   pc++;
08274 
08275                if (n_data > 1) {
08276                   info_str[0] = 0;
08277                   if (!*rec_str)
08278                      break;
08279 
08280                   for (j = 0; *rec_str != '\n' && *rec_str; j++)
08281                      info_str[j] = *rec_str++;
08282                   info_str[j] = 0;
08283                   if (*rec_str == '\n')
08284                      rec_str++;
08285                }
08286 
08287                for (i = 0; i < n_data; i++) {
08288                   /* strip trailing \n */
08289                   pc = &info_str[strlen(info_str) - 1];
08290                   while (*pc == '\n' || *pc == '\r')
08291                      *pc-- = 0;
08292 
08293                   if (tid == TID_STRING || tid == TID_LINK) {
08294                      if (!string_length) {
08295                         if (info_str[1] == '=')
08296                            string_length = -1;
08297                         else {
08298                            pc = strchr(info_str, '[');
08299                            if (pc != NULL)
08300                               string_length = atoi(pc + 1);
08301                            else
08302                               string_length = -1;
08303                         }
08304                         if (string_length > MAX_STRING_LENGTH) {
08305                            string_length = MAX_STRING_LENGTH;
08306                            cm_msg(MERROR, "db_check_record", "found string exceeding MAX_STRING_LENGTH");
08307                         }
08308                      }
08309 
08310                      if (string_length == -1) {
08311                         /* multi-line string */
08312                         if (strstr(rec_str, "\n====#$@$#====\n") != NULL) {
08313                            string_length = (POINTER_T) strstr(rec_str, "\n====#$@$#====\n") - (POINTER_T) rec_str + 1;
08314 
08315                            rec_str = strstr(rec_str, "\n====#$@$#====\n") + strlen("\n====#$@$#====\n");
08316                         } else
08317                            cm_msg(MERROR, "db_check_record", "found multi-line string without termination sequence");
08318                      } else {
08319                         if (strchr(info_str, ']'))
08320                            pc = strchr(info_str, ']') + 1;
08321                         else
08322                            pc = info_str + 2;
08323                         while (*pc && *pc != ' ')
08324                            pc++;
08325                         while (*pc && *pc == ' ')
08326                            pc++;
08327 
08328                         /* limit string size */
08329                         *(pc + string_length - 1) = 0;
08330                      }
08331                   } else {
08332                      pc = info_str;
08333 
08334                      if (n_data > 1 && info_str[0] == '[') {
08335                         pc = strchr(info_str, ']') + 1;
08336                         while (*pc && *pc == ' ')
08337                            pc++;
08338                      }
08339                   }
08340 
08341                   if (i < n_data - 1) {
08342                      info_str[0] = 0;
08343                      if (!*rec_str)
08344                         break;
08345 
08346                      pold = rec_str;
08347 
08348                      for (j = 0; *rec_str != '\n' && *rec_str; j++)
08349                         info_str[j] = *rec_str++;
08350                      info_str[j] = 0;
08351                      if (*rec_str == '\n')
08352                         rec_str++;
08353 
08354                      /* test if valid data */
08355                      if (tid != TID_STRING && tid != TID_LINK) {
08356                         if (info_str[0] == 0 || (strchr(info_str, '=')
08357                                                  && strchr(info_str, ':')))
08358                            rec_str = pold;
08359                      }
08360                   }
08361                }
08362 
08363                /* if rec_str contains key, but not ODB, return mismatch */
08364                if (!hKeyTest) {
08365                   if (correct)
08366                      return db_create_record(hDB, hKey, keyname, rec_str_orig);
08367 
08368                   return DB_STRUCT_MISMATCH;
08369                }
08370 
08371                status = db_get_key(hDB, hKeyTest, &key);
08372                assert(status == DB_SUCCESS);
08373 
08374                /* check rec_str vs. ODB key */
08375                if (!equal_ustring(key.name, key_name) || key.type != tid || key.num_values != n_data) {
08376                   if (correct)
08377                      return db_create_record(hDB, hKey, keyname, rec_str_orig);
08378 
08379                   return DB_STRUCT_MISMATCH;
08380                }
08381 
08382                /* get next key in ODB */
08383                db_get_next_link(hDB, hKeyTest, &hKeyTest);
08384             }
08385          }
08386       }
08387    } while (TRUE);
08388 
08389    return DB_SUCCESS;
08390 }

INT db_close_all_records (  ) 

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 8629 of file odb.c.

Referenced by cm_disconnect_experiment().

08630 {
08631    INT i;
08632 
08633    for (i = 0; i < _record_list_entries; i++) {
08634       if (_record_list[i].handle) {
08635          if (_record_list[i].access_mode & MODE_WRITE)
08636             free(_record_list[i].copy);
08637 
08638          if (_record_list[i].access_mode & MODE_ALLOC)
08639             free(_record_list[i].data);
08640 
08641          memset(&_record_list[i], 0, sizeof(RECORD_LIST));
08642       }
08643    }
08644 
08645    if (_record_list_entries > 0) {
08646       _record_list_entries = 0;
08647       free(_record_list);
08648    }
08649 
08650    return DB_SUCCESS;
08651 }

INT db_close_database ( HNDLE  hDB  ) 

Close a database

Parameters:
hDB ODB handle obtained via cm_get_experiment_database().
Returns:
DB_SUCCESS, DB_INVALID_HANDLE, RPC_NET_ERROR

Definition at line 1100 of file odb.c.

Referenced by rpc_server_dispatch().

01101 {
01102    if (rpc_is_remote())
01103       return rpc_call(RPC_DB_CLOSE_DATABASE, hDB);
01104 
01105 #ifdef LOCAL_ROUTINES
01106    else {
01107       DATABASE_HEADER *pheader;
01108       DATABASE_CLIENT *pclient;
01109       INT idx, destroy_flag, i, j;
01110 
01111       if (hDB > _database_entries || hDB <= 0) {
01112          cm_msg(MERROR, "db_close_database", "invalid database handle");
01113          return DB_INVALID_HANDLE;
01114       }
01115 
01116       /*
01117          Check if database was opened by current thread. This is necessary
01118          in the server process where one thread may not close the database
01119          of other threads.
01120        */
01121 
01122       /* first lock database */
01123       db_lock_database(hDB);
01124 
01125       idx = _database[hDB - 1].client_index;
01126       pheader = _database[hDB - 1].database_header;
01127       pclient = &pheader->client[idx];
01128 
01129       if (rpc_get_server_option(RPC_OSERVER_TYPE) == ST_SINGLE &&
01130           _database[hDB - 1].index != rpc_get_server_acception()) {
01131          db_unlock_database(hDB);
01132          return DB_INVALID_HANDLE;
01133       }
01134 
01135       if (rpc_get_server_option(RPC_OSERVER_TYPE) != ST_SINGLE && _database[hDB - 1].index != ss_gettid()) {
01136          db_unlock_database(hDB);
01137          return DB_INVALID_HANDLE;
01138       }
01139 
01140       if (!_database[hDB - 1].attached) {
01141          cm_msg(MERROR, "db_close_database", "invalid database handle");
01142          db_unlock_database(hDB);
01143          return DB_INVALID_HANDLE;
01144       }
01145 
01146       /* close all open records */
01147       for (i = 0; i < pclient->max_index; i++)
01148          if (pclient->open_record[i].handle)
01149             db_remove_open_record(hDB, pclient->open_record[i].handle, FALSE);
01150 
01151       /* mark entry in _database as empty */
01152       _database[hDB - 1].attached = FALSE;
01153 
01154       /* clear entry from client structure in database header */
01155       memset(&(pheader->client[idx]), 0, sizeof(DATABASE_CLIENT));
01156 
01157       /* calculate new max_client_index entry */
01158       for (i = MAX_CLIENTS - 1; i >= 0; i--)
01159          if (pheader->client[i].pid != 0)
01160             break;
01161       pheader->max_client_index = i + 1;
01162 
01163       /* count new number of clients */
01164       for (i = MAX_CLIENTS - 1, j = 0; i >= 0; i--)
01165          if (pheader->client[i].pid != 0)
01166             j++;
01167       pheader->num_clients = j;
01168 
01169       destroy_flag = (pheader->num_clients == 0);
01170 
01171       /* flush shared memory to disk */
01172       ss_shm_flush(pheader->name, pheader, sizeof(DATABASE_HEADER) + 2 * pheader->data_size, _database[hDB - 1].shm_handle);
01173 
01174       /* unmap shared memory, delete it if we are the last */
01175       ss_shm_close(pheader->name, pheader, _database[hDB - 1].shm_handle, destroy_flag);
01176 
01177       /* unlock database */
01178       db_unlock_database(hDB);
01179 
01180       /* delete semaphore */
01181       ss_semaphore_delete(_database[hDB - 1].semaphore, destroy_flag);
01182 
01183       /* update _database_entries */
01184       if (hDB == _database_entries)
01185          _database_entries--;
01186 
01187       if (_database_entries > 0)
01188          _database = (DATABASE *) realloc(_database, sizeof(DATABASE) * (_database_entries));
01189       else {
01190          free(_database);
01191          _database = NULL;
01192       }
01193 
01194       /* if we are the last one, also delete other semaphores */
01195       if (destroy_flag) {
01196          extern INT _semaphore_elog, _semaphore_alarm, _semaphore_history, _semaphore_msg;
01197 
01198          if (_semaphore_elog)
01199             ss_semaphore_delete(_semaphore_elog, TRUE);
01200          if (_semaphore_alarm)
01201             ss_semaphore_delete(_semaphore_alarm, TRUE);
01202          if (_semaphore_history)
01203             ss_semaphore_delete(_semaphore_history, TRUE);
01204          if (_semaphore_msg)
01205             ss_semaphore_delete(_semaphore_msg, TRUE);
01206       }
01207 
01208    }
01209 #endif                          /* LOCAL_ROUTINES */
01210 
01211    return DB_SUCCESS;
01212 }

INT db_close_record ( HNDLE  hDB,
HNDLE  hKey 
)

Close a record previously opend with db_open_record.

Parameters:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Handle for key where search starts, zero for root.
Returns:
DB_SUCCESS, DB_INVALID_HANDLE

Definition at line 8592 of file odb.c.

Referenced by banks_changed(), close_channels(), close_history(), command_loop(), init_module_parameters(), tr_start(), and tr_stop().

08593 {
08594 #ifdef LOCAL_ROUTINES
08595    {
08596       INT i;
08597 
08598       for (i = 0; i < _record_list_entries; i++)
08599          if (_record_list[i].handle == hKey && _record_list[i].hDB == hDB)
08600             break;
08601 
08602       if (i == _record_list_entries)
08603          return DB_INVALID_HANDLE;
08604 
08605       /* remove record entry from database structure */
08606       db_remove_open_record(hDB, hKey, TRUE);
08607 
08608       /* free local memory */
08609       if (_record_list[i].access_mode & MODE_ALLOC)
08610          free(_record_list[i].data);
08611 
08612       if (_record_list[i].access_mode & MODE_WRITE)
08613          free(_record_list[i].copy);
08614 
08615       memset(&_record_list[i], 0, sizeof(RECORD_LIST));
08616    }
08617 #endif                          /* LOCAL_ROUTINES */
08618 
08619    return DB_SUCCESS;
08620 }

INT db_copy ( HNDLE  hDB,
HNDLE  hKey,
char *  buffer,
INT buffer_size,
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:

Definition at line 5632 of file odb.c.

Referenced by command_loop(), db_create_record(), and db_save().

05633 {
05634    INT i, j, size, status;
05635    KEY key;
05636    HNDLE hSubkey;
05637    char full_path[MAX_ODB_PATH], str[MAX_STRING_LENGTH * 2];
05638    char *data, line[MAX_STRING_LENGTH * 2];
05639    BOOL bWritten;
05640 
05641    strcpy(full_path, path);
05642 
05643    bWritten = FALSE;
05644 
05645    /* first enumerate this level */
05646    for (i = 0;; i++) {
05647       db_enum_link(hDB, hKey, i, &hSubkey);
05648 
05649       if (i == 0 && !hSubkey) {
05650          /* If key has no subkeys, just write this key */
05651          status = db_get_link(hDB, hKey, &key);
05652          if (status != DB_SUCCESS)
05653             continue;
05654          size = key.total_size;
05655          data = (char *) malloc(size);
05656          if (data == NULL) {
05657             cm_msg(MERROR, "db_copy", "cannot allocate data buffer");
05658             return DB_NO_MEMORY;
05659          }
05660          line[0] = 0;
05661 
05662          if (key.type != TID_KEY) {
05663             status = db_get_link_data(hDB, hKey, data, &size, key.type);
05664             if (status != DB_SUCCESS)
05665                continue;
05666             if (key.num_values == 1) {
05667                sprintf(line, "%s = %s : ", key.name, tid_name[key.type]);
05668 
05669                if (key.type == TID_STRING && strchr(data, '\n') != NULL) {
05670                   /* multiline string */
05671                   sprintf(line + strlen(line), "[====#$@$#====]\n");
05672 
05673                   /* copy line to buffer */
05674                   if ((INT) (strlen(line) + 1) > *buffer_size) {
05675                      free(data);
05676                      return DB_TRUNCATED;
05677                   }
05678 
05679                   strcpy(buffer, line);
05680                   buffer += strlen(line);
05681                   *buffer_size -= strlen(line);
05682 
05683                   /* copy multiple lines to buffer */
05684                   if (key.item_size > *buffer_size) {
05685                      free(data);
05686                      return DB_TRUNCATED;
05687                   }
05688 
05689                   strcpy(buffer, data);
05690                   buffer += strlen(data);
05691                   *buffer_size -= strlen(data);
05692 
05693                   strcpy(line, "\n====#$@$#====\n");
05694                } else {
05695                   db_sprintf(str, data, key.item_size, 0, key.type);
05696 
05697                   if (key.type == TID_STRING || key.type == TID_LINK)
05698                      sprintf(line + strlen(line), "[%d] ", key.item_size);
05699 
05700                   sprintf(line + strlen(line), "%s\n", str);
05701                }
05702             } else {
05703                sprintf(line, "%s = %s[%d] :\n", key.name, tid_name[key.type], key.num_values);
05704 
05705                for (j = 0; j < key.num_values; j++) {
05706                   if (key.type == TID_STRING || key.type == TID_LINK)
05707                      sprintf(line + strlen(line), "[%d] ", key.item_size);
05708                   else
05709                      sprintf(line + strlen(line), "[%d] ", j);
05710 
05711                   db_sprintf(str, data, key.item_size, j, key.type);
05712                   sprintf(line + strlen(line), "%s\n", str);
05713 
05714                   /* copy line to buffer */
05715                   if ((INT) (strlen(line) + 1) > *buffer_size) {
05716                      free(data);
05717                      return DB_TRUNCATED;
05718                   }
05719 
05720                   strcpy(buffer, line);
05721                   buffer += strlen(line);
05722                   *buffer_size -= strlen(line);
05723                   line[0] = 0;
05724                }
05725             }
05726          }
05727 
05728          /* copy line to buffer */
05729          if ((INT) (strlen(line) + 1) > *buffer_size) {
05730             free(data);
05731             return DB_TRUNCATED;
05732          }
05733 
05734          strcpy(buffer, line);
05735          buffer += strlen(line);
05736          *buffer_size -= strlen(line);
05737 
05738          free(data);
05739       }
05740 
05741       if (!hSubkey)
05742          break;
05743 
05744       status = db_get_link(hDB, hSubkey, &key);
05745       if (status != DB_SUCCESS)
05746          continue;
05747 
05748       if (strcmp(key.name, "arr2") == 0)
05749          printf("\narr2\n");
05750       size = key.total_size;
05751       data = (char *) malloc(size);
05752       if (data == NULL) {
05753          cm_msg(MERROR, "db_copy", "cannot allocate data buffer");
05754          return DB_NO_MEMORY;
05755       }
05756 
05757       line[0] = 0;
05758 
05759       if (key.type == TID_KEY) {
05760          /* new line */
05761          if (bWritten) {
05762             if (*buffer_size < 2) {
05763                free(data);
05764                return DB_TRUNCATED;
05765             }
05766 
05767             strcpy(buffer, "\n");
05768             buffer += 1;
05769             *buffer_size -= 1;
05770          }
05771 
05772          strcpy(str, full_path);
05773          if (str[0] && str[strlen(str) - 1] != '/')
05774             strcat(str, "/");
05775          strcat(str, key.name);
05776 
05777          /* recurse */
05778          status = db_copy(hDB, hSubkey, buffer, buffer_size, str);
05779          if (status != DB_SUCCESS) {
05780             free(data);
05781             return status;
05782          }
05783 
05784          buffer += strlen(buffer);
05785          bWritten = FALSE;
05786       } else {
05787          status = db_get_link_data(hDB, hSubkey, data, &size, key.type);
05788          if (status != DB_SUCCESS)
05789             continue;
05790 
05791          if (!bWritten) {
05792             if (path[0] == 0)
05793                sprintf(line, "[.]\n");
05794             else
05795                sprintf(line, "[%s]\n", path);
05796             bWritten = TRUE;
05797          }
05798 
05799          if (key.num_values == 1) {
05800             sprintf(line + strlen(line), "%s = %s : ", key.name, tid_name[key.type]);
05801 
05802             if (key.type == TID_STRING && strchr(data, '\n') != NULL) {
05803                /* multiline string */
05804                sprintf(line + strlen(line), "[====#$@$#====]\n");
05805 
05806                /* ensure string limiter */
05807                data[size - 1] = 0;
05808 
05809                /* copy line to buffer */
05810                if ((INT) (strlen(line) + 1) > *buffer_size) {
05811                   free(data);
05812                   return DB_TRUNCATED;
05813                }
05814 
05815                strcpy(buffer, line);
05816                buffer += strlen(line);
05817                *buffer_size -= strlen(line);
05818 
05819                /* copy multiple lines to buffer */
05820                if (key.item_size > *buffer_size) {
05821                   free(data);
05822                   return DB_TRUNCATED;
05823                }
05824 
05825                strcpy(buffer, data);
05826                buffer += strlen(data);
05827                *buffer_size -= strlen(data);
05828 
05829                strcpy(line, "\n====#$@$#====\n");
05830             } else {
05831                db_sprintf(str, data, key.item_size, 0, key.type);
05832 
05833                if (key.type == TID_STRING || key.type == TID_LINK)
05834                   sprintf(line + strlen(line), "[%d] ", key.item_size);
05835 
05836                sprintf(line + strlen(line), "%s\n", str);
05837             }
05838          } else {
05839             sprintf(line + strlen(line), "%s = %s[%d] :\n", key.name, tid_name[key.type], key.num_values);
05840 
05841             for (j = 0; j < key.num_values; j++) {
05842                if (key.type == TID_STRING || key.type == TID_LINK)
05843                   sprintf(line + strlen(line), "[%d] ", key.item_size);
05844                else
05845                   sprintf(line + strlen(line), "[%d] ", j);
05846 
05847                db_sprintf(str, data, key.item_size, j, key.type);
05848                sprintf(line + strlen(line), "%s\n", str);
05849 
05850                /* copy line to buffer */
05851                if ((INT) (strlen(line) + 1) > *buffer_size) {
05852                   free(data);
05853                   return DB_TRUNCATED;
05854                }
05855 
05856                strcpy(buffer, line);
05857                buffer += strlen(line);
05858                *buffer_size -= strlen(line);
05859                line[0] = 0;
05860             }
05861          }
05862 
05863          /* copy line to buffer */
05864          if ((INT) (strlen(line) + 1) > *buffer_size) {
05865             free(data);
05866             return DB_TRUNCATED;
05867          }
05868 
05869          strcpy(buffer, line);
05870          buffer += strlen(line);
05871          *buffer_size -= strlen(line);
05872       }
05873 
05874       free(data);
05875    }
05876 
05877    if (bWritten) {
05878       if (*buffer_size < 2)
05879          return DB_TRUNCATED;
05880 
05881       strcpy(buffer, "\n");
05882       buffer += 1;
05883       *buffer_size -= 1;
05884    }
05885 
05886    return DB_SUCCESS;
05887 }

INT db_copy_xml ( HNDLE  hDB,
HNDLE  hKey,
char *  buffer,
INT buffer_size 
)

Copy an ODB subtree in XML format to a buffer

Parameters:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Handle for key where search starts, zero for root.
buffer ASCII buffer which receives ODB contents.
buffer_size Size of buffer, returns remaining space in buffer.
Returns:
DB_SUCCESS, DB_TRUNCATED, DB_NO_MEMORY

Definition at line 6343 of file odb.c.

Referenced by log_odb_dump().

06344 {
06345 #ifdef LOCAL_ROUTINES
06346    {
06347       INT len;
06348       char *p, str[256];
06349       MXML_WRITER *writer;
06350 
06351       /* open file */
06352       writer = mxml_open_buffer();
06353       if (writer == NULL) {
06354          cm_msg(MERROR, "db_copy_xml", "Cannot allocate buffer");
06355          return DB_NO_MEMORY;
06356       }
06357 
06358       db_get_path(hDB, hKey, str, sizeof(str));
06359 
06360       /* write XML header */
06361       mxml_start_element(writer, "odb");
06362       mxml_write_attribute(writer, "root", str);
06363       mxml_write_attribute(writer, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
06364       mxml_write_attribute(writer, "xsi:noNamespaceSchemaLocation", "http://midas.psi.ch/odb.xsd");
06365 
06366       db_save_xml_key(hDB, hKey, 0, writer);
06367 
06368       mxml_end_element(writer); // "odb"
06369       p = mxml_close_buffer(writer);
06370 
06371       strlcpy(buffer, p, *buffer_size);
06372       len = strlen(p);
06373       free(p);
06374       if (len > *buffer_size) {
06375          *buffer_size = 0;
06376          return DB_TRUNCATED;
06377       }
06378 
06379       *buffer_size -= len;
06380    }
06381 #endif                          /* LOCAL_ROUTINES */
06382 
06383    return DB_SUCCESS;
06384 }

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

Create a new key in a database

Parameters:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Key handle to start with, 0 for root
key_name Name of key in the form "/key/key/key"
type Type 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 1584 of file odb.c.

Referenced by add_event(), command_loop(), db_create_record(), db_get_value(), db_paste(), db_paste_node(), db_set_value(), db_set_value_index(), open_history(), register_equipment(), rpc_server_dispatch(), show_create_page(), show_custom_page(), show_elog_page(), show_hist_page(), and xdb_find_key().

01585 {
01586    if (rpc_is_remote())
01587       return rpc_call(RPC_DB_CREATE_KEY, hDB, hKey, key_name, type);
01588 
01589 #ifdef LOCAL_ROUTINES
01590    {
01591       DATABASE_HEADER *pheader;
01592       KEYLIST *pkeylist;
01593       KEY *pkey, *pprev_key, *pkeyparent;
01594       const char *pkey_name;
01595       char str[MAX_STRING_LENGTH];
01596       INT i;
01597 
01598       if (hDB > _database_entries || hDB <= 0) {
01599          cm_msg(MERROR, "db_create_key", "invalid database handle");
01600          return DB_INVALID_HANDLE;
01601       }
01602 
01603       if (!_database[hDB - 1].attached) {
01604          cm_msg(MERROR, "db_create_key", "invalid database handle");
01605          return DB_INVALID_HANDLE;
01606       }
01607 
01608       /* check type */
01609       if (type <= 0 || type >= TID_LAST) {
01610          cm_msg(MERROR, "db_create_key", "invalid key type %d for \'%s\'", type, key_name);
01611          return DB_INVALID_PARAM;
01612       }
01613 
01614       /* lock database */
01615       db_lock_database(hDB);
01616 
01617       pheader = _database[hDB - 1].database_header;
01618       if (!hKey)
01619          hKey = pheader->root_key;
01620       pkey = (KEY *) ((char *) pheader + hKey);
01621 
01622       /* check if hKey argument is correct */
01623       if (!db_validate_hkey(pheader, hKey)) {
01624          db_unlock_database(hDB);
01625          return DB_INVALID_HANDLE;
01626       }
01627 
01628       if (pkey->type != TID_KEY) {
01629          db_unlock_database(hDB);
01630          cm_msg(MERROR, "db_create_key", "key has no subkeys");
01631          return DB_NO_KEY;
01632       }
01633       pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
01634 
01635       pkey_name = key_name;
01636       do {
01637          /* extract single key from key_name */
01638          pkey_name = extract_key(pkey_name, str, sizeof(str));
01639 
01640          /* do not allow empty names, like '/dir/dir//dir/' */
01641          if (str[0] == 0) {
01642             db_unlock_database(hDB);
01643             return DB_INVALID_PARAM;
01644          }
01645 
01646          /* check if parent or current directory */
01647          if (strcmp(str, "..") == 0) {
01648             if (pkey->parent_keylist) {
01649                pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
01650                pkey = (KEY *) ((char *) pheader + pkeylist->parent);
01651             }
01652             continue;
01653          }
01654          if (strcmp(str, ".") == 0)
01655             continue;
01656 
01657          /* check if key is in keylist */
01658          pkey = (KEY *) ((char *) pheader + pkeylist->first_key);
01659          pprev_key = NULL;
01660 
01661          for (i = 0; i < pkeylist->num_keys; i++) {
01662             if (!db_validate_key_offset(pheader, pkey->next_key)) {
01663                cm_msg(MERROR, "db_create_key",
01664                       "Warning: database corruption, key %s, next_key 0x%08X",
01665                       key_name, pkey->next_key - sizeof(DATABASE_HEADER));
01666                db_unlock_database(hDB);
01667                return DB_CORRUPTED;
01668             }
01669 
01670             if (equal_ustring(str, pkey->name))
01671                break;
01672 
01673             pprev_key = pkey;
01674             pkey = (KEY *) ((char *) pheader + pkey->next_key);
01675          }
01676 
01677          if (i == pkeylist->num_keys) {
01678             /* not found: create new key */
01679 
01680             /* check parent for write access */
01681             pkeyparent = (KEY *) ((char *) pheader + pkeylist->parent);
01682             if (!(pkeyparent->access_mode & MODE_WRITE) || (pkeyparent->access_mode & MODE_EXCLUSIVE)) {
01683                db_unlock_database(hDB);
01684                return DB_NO_ACCESS;
01685             }
01686 
01687             pkeylist->num_keys++;
01688 
01689             if (*pkey_name == '/' || type == TID_KEY) {
01690                /* create new key with keylist */
01691                pkey = (KEY *) malloc_key(pheader, sizeof(KEY));
01692 
01693                if (pkey == NULL) {
01694                   db_unlock_database(hDB);
01695                   cm_msg(MERROR, "db_create_key", "online database full");
01696                   return DB_FULL;
01697                }
01698 
01699                /* append key to key list */
01700                if (pprev_key)
01701                   pprev_key->next_key = (POINTER_T) pkey - (POINTER_T) pheader;
01702                else
01703                   pkeylist->first_key = (POINTER_T) pkey - (POINTER_T) pheader;
01704 
01705                /* set key properties */
01706                pkey->type = TID_KEY;
01707                pkey->num_values = 1;
01708                pkey->access_mode = MODE_READ | MODE_WRITE | MODE_DELETE;
01709                strlcpy(pkey->name, str, sizeof(pkey->name));
01710                pkey->parent_keylist = (POINTER_T) pkeylist - (POINTER_T) pheader;
01711 
01712                /* find space for new keylist */
01713                pkeylist = (KEYLIST *) malloc_key(pheader, sizeof(KEYLIST));
01714 
01715                if (pkeylist == NULL) {
01716                   db_unlock_database(hDB);
01717                   cm_msg(MERROR, "db_create_key", "online database full");
01718                   return DB_FULL;
01719                }
01720 
01721                /* store keylist in data field */
01722                pkey->data = (POINTER_T) pkeylist - (POINTER_T) pheader;
01723                pkey->item_size = sizeof(KEYLIST);
01724                pkey->total_size = sizeof(KEYLIST);
01725 
01726                pkeylist->parent = (POINTER_T) pkey - (POINTER_T) pheader;
01727                pkeylist->num_keys = 0;
01728                pkeylist->first_key = 0;
01729             } else {
01730                /* create new key with data */
01731                pkey = (KEY *) malloc_key(pheader, sizeof(KEY));
01732 
01733                if (pkey == NULL) {
01734                   db_unlock_database(hDB);
01735                   cm_msg(MERROR, "db_create_key", "online database full");
01736                   return DB_FULL;
01737                }
01738 
01739                /* append key to key list */
01740                if (pprev_key)
01741                   pprev_key->next_key = (POINTER_T) pkey - (POINTER_T) pheader;
01742                else
01743                   pkeylist->first_key = (POINTER_T) pkey - (POINTER_T) pheader;
01744 
01745                pkey->type = type;
01746                pkey->num_values = 1;
01747                pkey->access_mode = MODE_READ | MODE_WRITE | MODE_DELETE;
01748                strlcpy(pkey->name, str, sizeof(pkey->name));
01749                pkey->parent_keylist = (POINTER_T) pkeylist - (POINTER_T) pheader;
01750 
01751                /* zero data */
01752                if (type != TID_STRING && type != TID_LINK) {
01753                   pkey->item_size = rpc_tid_size(type);
01754                   pkey->data = (POINTER_T) malloc_data(pheader, pkey->item_size);
01755                   pkey->total_size = pkey->item_size;
01756 
01757                   if (pkey->data == 0) {
01758                      db_unlock_database(hDB);
01759                      cm_msg(MERROR, "db_create_key", "online database full");
01760                      return DB_FULL;
01761                   }
01762 
01763                   pkey->data -= (POINTER_T) pheader;
01764                } else {
01765                   /* first data is empty */
01766                   pkey->item_size = 0;
01767                   pkey->total_size = 0;
01768                   pkey->data = 0;
01769                }
01770             }
01771          } else {
01772             /* key found: descend */
01773 
01774             /* resolve links */
01775             if (pkey->type == TID_LINK && pkey_name[0]) {
01776                /* copy destination, strip '/' */
01777                strcpy(str, (char *) pheader + pkey->data);
01778                if (str[strlen(str) - 1] == '/')
01779                   str[strlen(str) - 1] = 0;
01780 
01781                /* append rest of key name */
01782                strcat(str, pkey_name);
01783 
01784                db_unlock_database(hDB);
01785 
01786                return db_create_key(hDB, 0, str, type);
01787             }
01788 
01789             if (!(*pkey_name == '/')) {
01790                if ((WORD) pkey->type != type)
01791                   cm_msg(MERROR, "db_create_key", "redefinition of key type mismatch");
01792 
01793                db_unlock_database(hDB);
01794                return DB_KEY_EXIST;
01795             }
01796 
01797             if (pkey->type != TID_KEY) {
01798                db_unlock_database(hDB);
01799                cm_msg(MERROR, "db_create_key", "key used with value and as parent key");
01800                return DB_KEY_EXIST;
01801             }
01802 
01803             pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
01804          }
01805       } while (*pkey_name == '/');
01806 
01807       db_unlock_database(hDB);
01808    }
01809 #endif                          /* LOCAL_ROUTINES */
01810 
01811    return DB_SUCCESS;
01812 }

INT 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:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Key handle to start with, 0 for root
link_name Name of key in the form "/key/key/key"
destination Destination of link in the form "/key/key/key"
Returns:
DB_SUCCESS, DB_INVALID_HANDLE, DB_FULL, DB_KEY_EXIST, DB_NO_ACCESS

Definition at line 1823 of file odb.c.

Referenced by command_loop(), open_history(), rpc_server_dispatch(), and show_create_page().

01824 {
01825    HNDLE hkey;
01826    int status;
01827 
01828    if (rpc_is_remote())
01829       return rpc_call(RPC_DB_CREATE_LINK, hDB, hKey, link_name, destination);
01830 
01831    /* check if destination exists */
01832    status = db_find_key(hDB, hKey, destination, &hkey);
01833    if (status != DB_SUCCESS) {
01834       cm_msg(MERROR, "db_create_link", "Link destination \"%s\" does not exist", destination);
01835       return DB_NO_KEY;
01836    }
01837 
01838    return db_set_value(hDB, hKey, link_name, destination, strlen(destination) + 1, 1, TID_LINK);
01839 }

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

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;
} trigger_settings;
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",
    trigger_settings.level1,
    trigger_settings.level2);
}
main()
{
  HNDLE hDB, hkey;
  char[128] info;
  ...
  cm_get_experiment_database(&hDB, NULL);
  db_create_record(hDB, 0, "/Equipment/Trigger", trigger_settings_str);
  db_find_key(hDB, 0,"/Equipment/Trigger/Settings", &hkey);
  db_open_record(hDB, hkey, &trigger_settings,
    sizeof(trigger_settings), MODE_READ, trigger_update, info);
  ...
}
Parameters:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Handle for key where search starts, zero for root.
orig_key_name Name of key to search, can contain directories.
init_str Initialization 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 7989 of file odb.c.

Referenced by al_check(), al_trigger_alarm(), analyzer_init(), cm_set_client_info(), db_check_record(), frontend_init(), init_module_parameters(), logger_init(), main(), mana_init(), register_equipment(), register_requests(), rpc_server_dispatch(), and tr_start().

07990 {
07991    char str[256], key_name[256], *buffer;
07992    INT status, size, i, buffer_size;
07993    HNDLE hKeyTmp, hKeyTmpO, hKeyOrig, hSubkey;
07994 
07995    if (rpc_is_remote())
07996       return rpc_call(RPC_DB_CREATE_RECORD, hDB, hKey, orig_key_name, init_str);
07997 
07998    /* make this function atomic */
07999    db_lock_database(hDB);
08000 
08001    /* strip trailing '/' */
08002    strlcpy(key_name, orig_key_name, sizeof(key_name));
08003    if (strlen(key_name) > 1 && key_name[strlen(key_name) - 1] == '/')
08004       key_name[strlen(key_name) - 1] = 0;
08005 
08006    /* merge temporay record and original record */
08007    status = db_find_key(hDB, hKey, key_name, &hKeyOrig);
08008    if (status == DB_SUCCESS) {
08009       assert(hKeyOrig != 0);
08010       /* check if key or subkey is opened */
08011       open_count = 0;
08012       db_scan_tree_link(hDB, hKeyOrig, 0, check_open_keys, NULL);
08013       if (open_count) {
08014          db_unlock_database(hDB);
08015          return DB_OPEN_RECORD;
08016       }
08017 
08018       /* create temporary records */
08019       sprintf(str, "/System/Tmp/%1dI", ss_gettid());
08020       db_find_key(hDB, 0, str, &hKeyTmp);
08021       if (hKeyTmp)
08022          db_delete_key(hDB, hKeyTmp, FALSE);
08023       db_create_key(hDB, 0, str, TID_KEY);
08024       status = db_find_key(hDB, 0, str, &hKeyTmp);
08025       if (status != DB_SUCCESS) {
08026          db_unlock_database(hDB);
08027          return status;
08028       }
08029 
08030       sprintf(str, "/System/Tmp/%1dO", ss_gettid());
08031       db_find_key(hDB, 0, str, &hKeyTmpO);
08032       if (hKeyTmpO)
08033          db_delete_key(hDB, hKeyTmpO, FALSE);
08034       db_create_key(hDB, 0, str, TID_KEY);
08035       status = db_find_key(hDB, 0, str, &hKeyTmpO);
08036       if (status != DB_SUCCESS) {
08037          db_unlock_database(hDB);
08038          return status;
08039       }
08040 
08041       status = db_paste(hDB, hKeyTmp, init_str);
08042       if (status != DB_SUCCESS) {
08043          db_unlock_database(hDB);
08044          return status;
08045       }
08046 
08047       buffer_size = 10000;
08048       buffer = (char *) malloc(buffer_size);
08049       do {
08050          size = buffer_size;
08051          status = db_copy(hDB, hKeyOrig, buffer, &size, "");
08052          if (status == DB_TRUNCATED) {
08053             buffer_size += 10000;
08054             buffer = (char *) realloc(buffer, buffer_size);
08055             continue;
08056          }
08057          if (status != DB_SUCCESS) {
08058             db_unlock_database(hDB);
08059             return status;
08060          }
08061 
08062       } while (status != DB_SUCCESS);
08063 
08064       status = db_paste(hDB, hKeyTmpO, buffer);
08065       if (status != DB_SUCCESS) {
08066          free(buffer);
08067          db_unlock_database(hDB);
08068          return status;
08069       }
08070 
08071       /* merge temporay record and original record */
08072       db_scan_tree_link(hDB, hKeyTmpO, 0, merge_records, NULL);
08073 
08074       /* delete original record */
08075       for (i = 0;; i++) {
08076          db_enum_link(hDB, hKeyOrig, 0, &hSubkey);
08077          if (!hSubkey)
08078             break;
08079 
08080          status = db_delete_key(hDB, hSubkey, FALSE);
08081          if (status != DB_SUCCESS) {
08082             free(buffer);
08083             db_unlock_database(hDB);
08084             return status;
08085          }
08086       }
08087 
08088       /* copy merged record to original record */
08089       do {
08090          size = buffer_size;
08091          status = db_copy(hDB, hKeyTmp, buffer, &size, "");
08092          if (status == DB_TRUNCATED) {
08093             buffer_size += 10000;
08094             buffer = (char *) realloc(buffer, buffer_size);
08095             continue;
08096          }
08097          if (status != DB_SUCCESS) {
08098             free(buffer);
08099             db_unlock_database(hDB);
08100             return status;
08101          }
08102 
08103       } while (status != DB_SUCCESS);
08104 
08105       status = db_paste(hDB, hKeyOrig, buffer);
08106       if (status != DB_SUCCESS) {
08107          free(buffer);
08108          db_unlock_database(hDB);
08109          return status;
08110       }
08111 
08112       /* delete temporary records */
08113       db_delete_key(hDB, hKeyTmp, FALSE);
08114       db_delete_key(hDB, hKeyTmpO, FALSE);
08115 
08116       free(buffer);
08117    } else if (status == DB_NO_KEY) {
08118       /* create fresh record */
08119       db_create_key(hDB, hKey, key_name, TID_KEY);
08120       status = db_find_key(hDB, hKey, key_name, &hKeyTmp);
08121       if (status != DB_SUCCESS) {
08122          db_unlock_database(hDB);
08123          return status;
08124       }
08125 
08126       status = db_paste(hDB, hKeyTmp, init_str);
08127       if (status != DB_SUCCESS) {
08128          db_unlock_database(hDB);
08129          return status;
08130       }
08131    } else {
08132       cm_msg(MERROR, "db_create_record",
08133              "aborting on unexpected failure of db_find_key(%s), status %d", key_name, status);
08134       abort();
08135    }
08136 
08137    db_unlock_database(hDB);
08138 
08139    return DB_SUCCESS;
08140 }

INT 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);
    if (status != DB_SUCCESS)
    {
      cm_msg(MINFO,"my_delete"," "Cannot find key %s", str);
      return;
    }

    status = db_delete_key(hDB, hkey, FALSE);
    if (status != DB_SUCCESS)
    {
      cm_msg(MERROR,"my_delete"," "Cannot delete key %s", str);
      return;
    }
  ...
Parameters:
hDB ODB handle obtained via cm_get_experiment_database().
hKey for key where search starts, zero for root.
follow_links Follow links when TRUE.
Returns:
DB_SUCCESS, DB_INVALID_HANDLE, DB_NO_ACCESS, DB_OPEN_RECORD

Definition at line 2020 of file odb.c.

Referenced by add_event(), cm_deregister_transition(), cm_set_client_info(), command_loop(), db_create_record(), del_tree(), export_hist(), generate_hist_graph(), main(), rpc_server_dispatch(), show_delete_page(), and show_hist_page().

02021 {
02022    if (rpc_is_remote())
02023       return rpc_call(RPC_DB_DELETE_KEY, hDB, hKey, follow_links);
02024 
02025    return db_delete_key1(hDB, hKey, 0, follow_links);
02026 }

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

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

For internal use only.

Parameters:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Key handle to start with, 0 for root
level Recursion level, must be zero when
follow_links Follow links when TRUE called from a user routine
Returns:
DB_SUCCESS, DB_INVALID_HANDLE, DB_OPEN_RECORD

Definition at line 1851 of file odb.c.

Referenced by cm_delete_client_info(), and db_delete_key().

01852 {
01853 #ifdef LOCAL_ROUTINES
01854    {
01855       DATABASE_HEADER *pheader;
01856       KEYLIST *pkeylist;
01857       KEY *pkey, *pnext_key, *pkey_tmp;
01858       HNDLE hKeyLink;
01859       BOOL deny_delete;
01860       INT status;
01861 
01862       if (hDB > _database_entries || hDB <= 0) {
01863          cm_msg(MERROR, "db_delete_key1", "invalid database handle");
01864          return DB_INVALID_HANDLE;
01865       }
01866 
01867       if (!_database[hDB - 1].attached) {
01868          cm_msg(MERROR, "db_delete_key1", "invalid database handle");
01869          return DB_INVALID_HANDLE;
01870       }
01871 
01872       if (hKey < (int) sizeof(DATABASE_HEADER)) {
01873          cm_msg(MERROR, "db_delete_key1", "invalid key handle");
01874          return DB_INVALID_HANDLE;
01875       }
01876 
01877       /* lock database at the top level */
01878       if (level == 0)
01879          db_lock_database(hDB);
01880 
01881       pheader = _database[hDB - 1].database_header;
01882 
01883       pkey = (KEY *) ((char *) pheader + hKey);
01884 
01885       /* check if hKey argument is correct */
01886       if (!db_validate_hkey(pheader, hKey)) {
01887          db_unlock_database(hDB);
01888          return DB_INVALID_HANDLE;
01889       }
01890 
01891       /* check if someone has opened key or parent */
01892       if (level == 0)
01893          do {
01894             if (pkey->notify_count) {
01895                db_unlock_database(hDB);
01896                return DB_OPEN_RECORD;
01897             }
01898 
01899             if (pkey->parent_keylist == 0)
01900                break;
01901 
01902             pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
01903             pkey = (KEY *) ((char *) pheader + pkeylist->parent);
01904          } while (TRUE);
01905 
01906       pkey = (KEY *) ((char *) pheader + hKey);
01907       pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
01908 
01909       deny_delete = FALSE;
01910 
01911       /* first recures subtree for keys */
01912       if (pkey->type == TID_KEY && pkeylist->first_key) {
01913          pkey = (KEY *) ((char *) pheader + pkeylist->first_key);
01914 
01915          do {
01916             pnext_key = (KEY *) (POINTER_T) pkey->next_key;
01917 
01918             status = db_delete_key1(hDB, (POINTER_T) pkey - (POINTER_T) pheader, level + 1, follow_links);
01919 
01920             if (status == DB_NO_ACCESS)
01921                deny_delete = TRUE;
01922 
01923             if (pnext_key)
01924                pkey = (KEY *) ((char *) pheader + (POINTER_T) pnext_key);
01925          } while (pnext_key);
01926       }
01927 
01928       /* follow links if requested */
01929       if (pkey->type == TID_LINK && follow_links) {
01930          status = db_find_key(hDB, 0, (char *) pheader + pkey->data, &hKeyLink);
01931          if (status == DB_SUCCESS && follow_links < 100)
01932             db_delete_key1(hDB, hKeyLink, level + 1, follow_links + 1);
01933 
01934          if (follow_links == 100)
01935             cm_msg(MERROR, "db_delete_key1", "try to delete cyclic link");
01936       }
01937 
01938       pkey = (KEY *) ((char *) pheader + hKey);
01939 
01940       /* return if key was already deleted by cyclic link */
01941       if (pkey->parent_keylist == 0) {
01942          if (level == 0)
01943             db_unlock_database(hDB);
01944          return DB_SUCCESS;
01945       }
01946 
01947       /* now delete key */
01948       if (hKey != pheader->root_key) {
01949          if (!(pkey->access_mode & MODE_DELETE) || deny_delete) {
01950             if (level == 0)
01951                db_unlock_database(hDB);
01952             return DB_NO_ACCESS;
01953          }
01954 
01955          if (pkey->notify_count) {
01956             if (level == 0)
01957                db_unlock_database(hDB);
01958             return DB_OPEN_RECORD;
01959          }
01960 
01961          /* delete key data */
01962          if (pkey->type == TID_KEY)
01963             free_key(pheader, (char *) pheader + pkey->data, pkey->total_size);
01964          else
01965             free_data(pheader, (char *) pheader + pkey->data, pkey->total_size);
01966 
01967          /* unlink key from list */
01968          pnext_key = (KEY *) (POINTER_T) pkey->next_key;
01969          pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
01970 
01971          if ((KEY *) ((char *) pheader + pkeylist->first_key) == pkey) {
01972             /* key is first in list */
01973             pkeylist->first_key = (POINTER_T) pnext_key;
01974          } else {
01975             /* find predecessor */
01976             pkey_tmp = (KEY *) ((char *) pheader + pkeylist->first_key);
01977             while ((KEY *) ((char *) pheader + pkey_tmp->next_key) != pkey)
01978                pkey_tmp = (KEY *) ((char *) pheader + pkey_tmp->next_key);
01979             pkey_tmp->next_key = (POINTER_T) pnext_key;
01980          }
01981 
01982          /* delete key */
01983          free_key(pheader, pkey, sizeof(KEY));
01984          pkeylist->num_keys--;
01985       }
01986 
01987       if (level == 0)
01988          db_unlock_database(hDB);
01989    }
01990 #endif                          /* LOCAL_ROUTINES */
01991 
01992    return DB_SUCCESS;
01993 }

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

INT   i;
HNDLE hkey, hsubkey;
KEY   key;
  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);
  }
Parameters:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Handle for key where search starts, zero for root.
idx Subkey index, sould be initially 0, then incremented in each call until subhKey becomes zero and the function returns DB_NO_MORE_SUBKEYS
subkey_handle Handle 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 3326 of file odb.c.

Referenced by add_event(), al_check(), ascii_write(), book_ntuples(), build_done_list_odb(), close_history(), cm_connect_client(), cm_exist(), cm_set_client_info(), cm_shutdown(), cm_transition1(), command_loop(), create_experim_h(), db_get_event_definition(), do_jrpc_rev0(), dump_write(), exec_script(), export_hist(), gen_odb_attachment(), generate_hist_graph(), get_event_id(), get_variable_id(), get_variable_id_tags(), MidasHistory::GetEventsFromEquipment(), MidasHistory::GetEventsFromOdbEvents(), MidasHistory::GetEventsFromOdbTags(), MidasHistory::GetTagsFromOdb(), interprete(), load_fragment(), log_callback(), log_system_history(), logger_init(), logger_root(), main(), odb_load(), open_history(), rpc_server_dispatch(), show_cnaf_page(), show_custom_gif(), show_delete_page(), show_odb_page(), show_programs_page(), show_sc_page(), show_start_page(), show_status_page(), tr_start(), update_odb(), write_event_ascii(), write_event_hbook(), and write_event_odb().

03327 {
03328    if (rpc_is_remote())
03329       return rpc_call(RPC_DB_ENUM_KEY, hDB, hKey, idx, subkey_handle);
03330 
03331 #ifdef LOCAL_ROUTINES
03332    {
03333       DATABASE_HEADER *pheader;
03334       KEYLIST *pkeylist;
03335       KEY *pkey;
03336       INT i;
03337       char str[256];
03338       HNDLE parent;
03339 
03340       if (hDB > _database_entries || hDB <= 0) {
03341          cm_msg(MERROR, "db_enum_key", "invalid database handle");
03342          return DB_INVALID_HANDLE;
03343       }
03344 
03345       if (!_database[hDB - 1].attached) {
03346          cm_msg(MERROR, "db_enum_key", "invalid database handle");
03347          return DB_INVALID_HANDLE;
03348       }
03349 
03350       *subkey_handle = 0;
03351 
03352       /* first lock database */
03353       db_lock_database(hDB);
03354 
03355       pheader = _database[hDB - 1].database_header;
03356       if (!hKey)
03357          hKey = pheader->root_key;
03358       pkey = (KEY *) ((char *) pheader + hKey);
03359 
03360       /* check if hKey argument is correct */
03361       if (!db_validate_hkey(pheader, hKey)) {
03362          db_unlock_database(hDB);
03363          return DB_INVALID_HANDLE;
03364       }
03365 
03366       if (pkey->type != TID_KEY) {
03367          db_unlock_database(hDB);
03368          return DB_NO_MORE_SUBKEYS;
03369       }
03370       pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
03371 
03372       if (idx >= pkeylist->num_keys) {
03373          db_unlock_database(hDB);
03374          return DB_NO_MORE_SUBKEYS;
03375       }
03376 
03377       pkey = (KEY *) ((char *) pheader + pkeylist->first_key);
03378       for (i = 0; i < idx; i++)
03379          pkey = (KEY *) ((char *) pheader + pkey->next_key);
03380 
03381       /* resolve links */
03382       if (pkey->type == TID_LINK) {
03383          strcpy(str, (char *) pheader + pkey->data);
03384 
03385          /* no not reolve if link to array index */
03386          if (strlen(str) > 0 && str[strlen(str) - 1] == ']') {
03387             *subkey_handle = (POINTER_T) pkey - (POINTER_T) pheader;
03388             db_unlock_database(hDB);
03389             return DB_SUCCESS;
03390          }
03391 
03392          if (*str == '/') {
03393             /* absolute path */
03394             db_unlock_database(hDB);
03395             return db_find_key(hDB, 0, str, subkey_handle);
03396          } else {
03397             /* relative path */
03398             if (pkey->parent_keylist) {
03399                pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
03400                parent = pkeylist->parent;
03401                db_unlock_database(hDB);
03402                return db_find_key(hDB, parent, str, subkey_handle);
03403             } else {
03404                db_unlock_database(hDB);
03405                return db_find_key(hDB, 0, str, subkey_handle);
03406             }
03407          }
03408       }
03409 
03410       *subkey_handle = (POINTER_T) pkey - (POINTER_T) pheader;
03411       db_unlock_database(hDB);
03412    }
03413 #endif                          /* LOCAL_ROUTINES */
03414 
03415    return DB_SUCCESS;
03416 }

INT 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:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Handle for key where search starts, zero for root.
key_name Name of key to search, can contain directories.
subhKey Returned handle of key, zero if key cannot be found.
Returns:
DB_SUCCESS, DB_INVALID_HANDLE, DB_NO_ACCESS, DB_NO_KEY

Definition at line 2053 of file odb.c.

Referenced by add_data_dir(), add_event(), al_check(), al_reset_alarm(), al_trigger_alarm(), analyzer_init(), banks_changed(), book_ntuples(), build_done_list_odb(), check_web_password(), close_history(), cm_connect_client(), cm_deregister_transition(), cm_exist(), cm_get_client_info(), cm_msg_log(), cm_msg_log1(), cm_msg_retrieve(), cm_register_deferred_transition(), cm_register_transition(), cm_set_client_info(), cm_shutdown(), cm_transition1(), cmd_dir(), command_loop(), condition_test(), create_experim_h(), db_check_record(), db_create_link(), db_create_record(), db_delete_key1(), db_enum_key(), db_get_data(), db_get_event_definition(), db_get_key(), db_get_value(), db_paste(), db_paste_xml(), db_set_data(), db_set_data_index(), db_set_value(), db_set_value_index(), do_jrpc_rev0(), evaluate_src(), export_hist(), frontend_init(), gen_odb_attachment(), generate_hist_graph(), get_event_id(), get_variable_id(), get_variable_id_tags(), MidasHistory::GetEventsFromEquipment(), MidasHistory::GetEventsFromOdbEvents(), MidasHistory::GetEventsFromOdbTags(), MidasHistory::GetTagsFromEquipment(), MidasHistory::GetTagsFromOdb(), MidasHistory::hs_connect(), init_module_parameters(), interprete(), is_editable(), lazy_main(), lazy_maintain_free_space(), load_fragment(), load_parameters(), log_callback(), logger_init(), logger_root(), main(), mana_init(), odb_load(), open_history(), print_key(), register_equipment(), register_requests(), rpc_server_dispatch(), set_equipment_status(), show_alarm_page(), show_cnaf_page(), show_create_page(), show_custom_gif(), show_custom_page(), show_delete_page(), show_elog_new(), show_elog_page(), show_elog_query(), show_find_page(), show_form_query(), show_hist_page(), show_odb_page(), show_odb_tag(), show_programs_page(), show_sc_page(), show_start_page(), show_status_page(), submit_elog(), submit_form(), tr_start(), update_odb(), write_event_odb(), xdb_find_key(), and xdb_get_data_index().

02054 {
02055    if (rpc_is_remote())
02056       return rpc_call(RPC_DB_FIND_KEY, hDB, hKey, key_name, subhKey);
02057 
02058 #ifdef LOCAL_ROUTINES
02059    {
02060       DATABASE_HEADER *pheader;
02061       KEYLIST *pkeylist;
02062       KEY *pkey;
02063       const char *pkey_name;
02064       char str[MAX_STRING_LENGTH];
02065       INT i, status;
02066 
02067       *subhKey = 0;
02068 
02069       if (hDB > _database_entries || hDB <= 0) {
02070          cm_msg(MERROR, "db_find_key", "invalid database handle");
02071          return DB_INVALID_HANDLE;
02072       }
02073 
02074       if (!_database[hDB - 1].attached) {
02075          cm_msg(MERROR, "db_find_key", "invalid database handle");
02076          return DB_INVALID_HANDLE;
02077       }
02078 
02079       db_lock_database(hDB);
02080 
02081       pheader = _database[hDB - 1].database_header;
02082 
02083       if (!hKey)
02084          hKey = pheader->root_key;
02085 
02086       pkey = (KEY *) ((char *) pheader + hKey);
02087 
02088       /* check if hKey argument is correct */
02089       if (!db_validate_hkey(pheader, hKey)) {
02090          db_unlock_database(hDB);
02091          return DB_INVALID_HANDLE;
02092       }
02093 
02094       if (pkey->type != TID_KEY) {
02095          db_get_path(hDB, hKey, str, sizeof(str));
02096          cm_msg(MERROR, "db_find_key", "key \"%s\" has no subkeys", str);
02097          *subhKey = 0;
02098          db_unlock_database(hDB);
02099          return DB_NO_KEY;
02100       }
02101       pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
02102 
02103       if (key_name[0] == 0 || strcmp(key_name, "/") == 0) {
02104          if (!(pkey->access_mode & MODE_READ)) {
02105             *subhKey = 0;
02106             db_unlock_database(hDB);
02107             return DB_NO_ACCESS;
02108          }
02109 
02110          *subhKey = (POINTER_T) pkey - (POINTER_T) pheader;
02111 
02112          db_unlock_database(hDB);
02113          return DB_SUCCESS;
02114       }
02115 
02116       pkey_name = key_name;
02117       do {
02118          /* extract single subkey from key_name */
02119          pkey_name = extract_key(pkey_name, str, sizeof(str));
02120 
02121          /* strip trailing '[n]' */
02122          if (strchr(str, '[') && str[strlen(str) - 1] == ']')
02123             *strchr(str, '[') = 0;
02124 
02125          /* check if parent or current directory */
02126          if (strcmp(str, "..") == 0) {
02127             if (pkey->parent_keylist) {
02128                pkeylist = (KEYLIST *) ((char *) pheader + pkey->parent_keylist);
02129                pkey = (KEY *) ((char *) pheader + pkeylist->parent);
02130             }
02131             continue;
02132          }
02133          if (strcmp(str, ".") == 0)
02134             continue;
02135 
02136          /* check if key is in keylist */
02137          pkey = (KEY *) ((char *) pheader + pkeylist->first_key);
02138 
02139          for (i = 0; i < pkeylist->num_keys; i++) {
02140             if (pkey->name[0] == 0 || !db_validate_key_offset(pheader, pkey->next_key)) {
02141                cm_msg(MERROR, "db_find_key",
02142                       "Warning: database corruption, key %s, next_key 0x%08X",
02143                       key_name, pkey->next_key - sizeof(DATABASE_HEADER));
02144                *subhKey = 0;
02145                db_unlock_database(hDB);
02146                return DB_CORRUPTED;
02147             }
02148 
02149             if (equal_ustring(str, pkey->name))
02150                break;
02151 
02152             pkey = (KEY *) ((char *) pheader + pkey->next_key);
02153          }
02154 
02155          if (i == pkeylist->num_keys) {
02156             *subhKey = 0;
02157             db_unlock_database(hDB);
02158             return DB_NO_KEY;
02159          }
02160 
02161          /* resolve links */
02162          if (pkey->type == TID_LINK) {
02163             /* copy destination, strip '/' */
02164             strcpy(str, (char *) pheader + pkey->data);
02165             if (str[strlen(str) - 1] == '/')
02166                str[strlen(str) - 1] = 0;
02167 
02168             /* if link is pointer to array index, return link instead of destination */
02169             if (str[strlen(str) - 1] == ']')
02170                break;
02171 
02172             /* append rest of key name if existing */
02173             if (pkey_name[0]) {
02174                strcat(str, pkey_name);
02175                db_unlock_database(hDB);
02176                return db_find_key(hDB, 0, str, subhKey);
02177             } else {
02178                /* if last key in chain is a link, return its destination */
02179                db_unlock_database(hDB);
02180                status = db_find_link(hDB, 0, str, subhKey);
02181                if (status == DB_NO_KEY)
02182                   return DB_INVALID_LINK;
02183                return status;
02184             }
02185          }
02186 
02187          /* key found: check if last in chain */
02188          if (*pkey_name == '/') {
02189             if (pkey->type != TID_KEY) {
02190                *subhKey = 0;
02191                db_unlock_database(hDB);
02192                return DB_NO_KEY;
02193             }
02194          }
02195 
02196          /* descend one level */
02197          pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
02198 
02199       } while (*pkey_name == '/' && *(pkey_name + 1));
02200 
02201       *subhKey = (POINTER_T) pkey - (POINTER_T) pheader;
02202 
02203       db_unlock_database(hDB);
02204    }
02205 #endif                          /* LOCAL_ROUTINES */
02206 
02207    return DB_SUCCESS;
02208 }

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

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;
  INT   run_number, size;
  // get key handle for run number
  db_find_key(hDB, 0, "/Runinfo/Run number", &hkey);
  // return run number
  size = sizeof(run_number);
  db_get_data(hDB, hkey, &run_number, &size,TID_INT);
Parameters:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Handle for key where search starts, zero for root.
data Pointer to the return data.
buf_size Size of data buffer.
type Type of key, one of TID_xxx (see Midas Data Types).
Returns:
DB_SUCCESS, DB_INVALID_HANDLE, DB_TRUNCATED, DB_TYPE_MISMATCH

Definition at line 4180 of file odb.c.

Referenced by add_data_dir(), add_event(), build_done_list_odb(), check_web_password(), cm_connect_client(), cm_get_client_info(), cm_set_client_info(), command_loop(), db_get_record(), exec_script(), gen_odb_attachment(), get_event_id(), get_variable_id(), MidasHistory::GetEventsFromOdbEvents(), MidasHistory::GetTagsFromOdb(), interprete(), log_system_history(), main(), print_key(), rpc_server_dispatch(), scan_tree(), search_callback(), search_key(), show_custom_page(), show_elog_new(), show_elog_query(), show_form_query(), show_odb_page(), show_sc_page(), show_set_page(), show_start_page(), show_status_page(), submit_elog(), submit_form(), and tr_start().

04181 {
04182    if (rpc_is_remote())
04183       return rpc_call(RPC_DB_GET_DATA, hDB, hKey, data, buf_size, type);
04184 
04185 #ifdef LOCAL_ROUTINES
04186    {
04187       DATABASE_HEADER *pheader;
04188       KEY *pkey;
04189       char str[256];
04190 
04191       if (hDB > _database_entries || hDB <= 0) {
04192          cm_msg(MERROR, "db_get_data", "Invalid database handle");
04193          return DB_INVALID_HANDLE;
04194       }
04195 
04196       if (!_database[hDB - 1].attached) {
04197          cm_msg(MERROR, "db_get_data", "invalid database handle");
04198          return DB_INVALID_HANDLE;
04199       }
04200 
04201       if (hKey < (int) sizeof(DATABASE_HEADER)) {
04202          cm_msg(MERROR, "db_get_data", "invalid key handle");
04203          return DB_INVALID_HANDLE;
04204       }
04205 
04206       db_lock_database(hDB);
04207 
04208       pheader = _database[hDB - 1].database_header;
04209       pkey = (KEY *) ((char *) pheader + hKey);
04210 
04211       /* check if hKey argument is correct */
04212       if (!db_validate_hkey(pheader, hKey)) {
04213          db_unlock_database(hDB);
04214          return DB_INVALID_HANDLE;
04215       }
04216 
04217       /* check for read access */
04218       if (!(pkey->access_mode & MODE_READ)) {
04219          db_unlock_database(hDB);
04220          return DB_NO_ACCESS;
04221       }
04222 
04223       if (!pkey->type) {
04224          db_unlock_database(hDB);
04225          cm_msg(MERROR, "db_get_data", "invalid key type %d", pkey->type);
04226          return DB_INVALID_HANDLE;
04227       }
04228 
04229       /* follow links to array index */
04230       if (pkey->type == TID_LINK) {
04231          char link_name[256];
04232          int i;
04233          HNDLE hkey;
04234          KEY key;
04235 
04236          strlcpy(link_name, (char *) pheader + pkey->data, sizeof(link_name));
04237          if (strlen(link_name) > 0 && link_name[strlen(link_name) - 1] == ']') {
04238             db_unlock_database(hDB);
04239             if (strchr(link_name, '[') == NULL)
04240                return DB_INVALID_LINK;
04241             i = atoi(strchr(link_name, '[') + 1);
04242             *strchr(link_name, '[') = 0;
04243             if (db_find_key(hDB, 0, link_name, &hkey) != DB_SUCCESS)
04244                return DB_INVALID_LINK;
04245             db_get_key(hDB, hkey, &key);
04246             return db_get_data_index(hDB, hkey, data, buf_size, i, key.type);
04247          }
04248       }
04249 
04250       if (pkey->type != type) {
04251          db_unlock_database(hDB);
04252          db_get_path(hDB, hKey, str, sizeof(str));
04253          cm_msg(MERROR, "db_get_data", "\"%s\" is of type %s, not %s",
04254                 str, rpc_tid_name(pkey->type), rpc_tid_name(type));
04255          return DB_TYPE_MISMATCH;
04256       }
04257 
04258       /* keys cannot contain data */
04259       if (pkey->type == TID_KEY) {
04260          db_unlock_database(hDB);
04261          db_get_path(hDB, hKey, str, sizeof(str));
04262          cm_msg(MERROR, "db_get_data", "Key \"%s\" cannot contain data", str);
04263          return DB_TYPE_MISMATCH;
04264       }
04265 
04266       /* check if key has data */
04267       if (pkey->data == 0) {
04268          memset(data, 0, *buf_size);
04269          *buf_size = 0;
04270          db_unlock_database(hDB);
04271          return DB_SUCCESS;
04272       }
04273 
04274       /* check if buffer is too small */
04275       if (pkey->num_values * pkey->item_size > *buf_size) {
04276          memcpy(data, (char *) pheader + pkey->data, *buf_size);
04277          db_unlock_database(hDB);
04278          db_get_path(hDB, hKey, str, sizeof(str));
04279          cm_msg(MERROR, "db_get_data", "data for key \"%s\" truncated", str);
04280          return DB_TRUNCATED;
04281       }
04282 
04283       /* copy key data */
04284       memcpy(data, (char *) pheader + pkey->data, pkey->num_values * pkey->item_size);
04285       *buf_size = pkey->num_values * pkey->item_size;
04286 
04287       db_unlock_database(hDB);
04288 
04289    }
04290 #endif                          /* LOCAL_ROUTINES */
04291 
04292    return DB_SUCCESS;
04293 }

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

returns a single value of keys containing arrays of values.

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

Parameters:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Handle for key where search starts, zero for root.
data Size of data buffer.
buf_size Return size of the record.
idx Index of array [0..n-1].
type Type 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 4531 of file odb.c.

Referenced by cm_transition1(), condition_test(), db_get_data(), export_hist(), gen_odb_attachment(), generate_hist_graph(), get_variable_id_tags(), MidasHistory::GetEventsFromOdbTags(), MidasHistory::GetTagsFromEquipment(), MidasHistory::GetTagsFromOdb(), is_editable(), open_history(), rpc_server_dispatch(), show_custom_gif(), show_custom_page(), show_elog_page(), show_hist_page(), show_odb_page(), show_odb_tag(), show_sc_page(), and xdb_get_data_index().

04532 {
04533    if (rpc_is_remote())
04534       return rpc_call(RPC_DB_GET_DATA_INDEX, hDB, hKey, data, buf_size, idx, type);
04535 
04536 #ifdef LOCAL_ROUTINES
04537    {
04538       DATABASE_HEADER *pheader;
04539       KEY *pkey;
04540       char str[256];
04541 
04542       if (hDB > _database_entries || hDB <= 0) {
04543          cm_msg(MERROR, "db_get_data", "Invalid database handle");
04544          return DB_INVALID_HANDLE;
04545       }
04546 
04547       if (!_database[hDB - 1].attached) {
04548          cm_msg(MERROR, "db_get_data", "invalid database handle");
04549          return DB_INVALID_HANDLE;
04550       }
04551 
04552       if (hKey < (int) sizeof(DATABASE_HEADER)) {
04553          cm_msg(MERROR, "db_get_data", "invalid key handle");
04554          return DB_INVALID_HANDLE;
04555       }
04556 
04557       db_lock_database(hDB);
04558 
04559       pheader = _database[hDB - 1].database_header;
04560       pkey = (KEY *) ((char *) pheader + hKey);
04561 
04562       /* check if hKey argument is correct */
04563       if (!db_validate_hkey(pheader, hKey)) {
04564          db_unlock_database(hDB);
04565          return DB_INVALID_HANDLE;
04566       }
04567 
04568       /* check for read access */
04569       if (!(pkey->access_mode & MODE_READ)) {
04570          db_unlock_database(hDB);
04571          return DB_NO_ACCESS;
04572       }
04573 
04574       if (!pkey->type) {
04575          db_unlock_database(hDB);
04576          cm_msg(MERROR, "db_get_data_index", "invalid key type %d", pkey->type);
04577          return DB_INVALID_HANDLE;
04578       }
04579 
04580       if (pkey->type != type) {
04581          db_unlock_database(hDB);
04582          cm_msg(MERROR, "db_get_data_index",
04583                 "\"%s\" is of type %s, not %s", pkey->name, rpc_tid_name(pkey->type), rpc_tid_name(type));
04584          return DB_TYPE_MISMATCH;
04585       }
04586 
04587       /* keys cannot contain data */
04588       if (pkey->type == TID_KEY) {
04589          db_unlock_database(hDB);
04590          cm_msg(MERROR, "db_get_data_index", "Key cannot contain data");
04591          return DB_TYPE_MISMATCH;
04592       }
04593 
04594       /* check if key has data */
04595       if (pkey->data == 0) {
04596          memset(data, 0, *buf_size);
04597          *buf_size = 0;
04598          db_unlock_database(hDB);
04599          return DB_SUCCESS;
04600       }
04601 
04602       /* check if index in range */
04603       if (idx < 0 || idx >= pkey->num_values) {
04604          memset(data, 0, *buf_size);
04605          db_unlock_database(hDB);
04606 
04607          db_get_path(hDB, hKey, str, sizeof(str));
04608          cm_msg(MERROR, "db_get_data_index",
04609                 "index (%d) exceeds array length (%d) for key \"%s\"", idx, pkey->num_values, str);
04610          return DB_OUT_OF_RANGE;
04611       }
04612 
04613       /* check if buffer is too small */
04614       if (pkey->item_size > *buf_size) {
04615          /* copy data */
04616          memcpy(data, (char *) pheader + pkey->data + idx * pkey->item_size, *buf_size);
04617          db_unlock_database(hDB);
04618          cm_msg(MERROR, "db_get_data_index", "data for key \"%s\" truncated", pkey->name);
04619          return DB_TRUNCATED;
04620       }
04621 
04622       /* copy key data */
04623       memcpy(data, (char *) pheader + pkey->data + idx * pkey->item_size, pkey->item_size);
04624       *buf_size = pkey->item_size;
04625 
04626       db_unlock_database(hDB);
04627 
04628    }
04629 #endif                          /* LOCAL_ROUTINES */
04630 
04631    return DB_SUCCESS;
04632 }

INT 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, num_values, and name. 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.
KEY   key;
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:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Handle for key where search starts, zero for root.
key Pointer to KEY stucture.
Returns:
DB_SUCCESS, DB_INVALID_HANDLE

Definition at line 3665 of file odb.c.

Referenced by add_event(), al_check(), al_reset_alarm(), ascii_write(), book_ntuples(), build_done_list(), build_done_list_odb(), cm_check_client(), cm_register_transition(), cm_shutdown(), cm_transition1(), command_loop(), condition_test(), convert_done_list(), create_experim_h(), db_check_record(), db_get_data(), db_get_record(), db_get_record_size(), db_open_record(), db_paste(), db_save_struct(), db_set_record(), del_tree(), dump_write(), evaluate_src(), exec_script(), export_hist(), gen_odb_attachment(), generate_hist_graph(), get_event_id(), get_variable_id(), get_variable_id_tags(), MidasHistory::GetEventsFromEquipment(), MidasHistory::GetEventsFromOdbTags(), MidasHistory::GetTagsFromEquipment(), MidasHistory::GetTagsFromOdb(), interprete(), is_editable(), load_fragment(), load_parameters(), log_system_history(), logger_init(), main(), open_history(), print_key(), rpc_server_dispatch(), save_done_list(), scan_tree(), show_alarm_page(), show_create_page(), show_custom_gif(), show_custom_page(), show_elog_new(), show_elog_page(), show_elog_query(), show_form_query(), show_hist_page(), show_odb_page(), show_odb_tag(), show_programs_page(), show_sc_page(), show_set_page(), show_start_page(), show_status_page(), submit_form(), tr_start(), update_odb(), write_event_ascii(), write_event_hbook(), write_event_odb(), and xdb_get_data_index().

03666 {
03667    if (rpc_is_remote())
03668       return rpc_call(RPC_DB_GET_KEY, hDB, hKey, key);
03669 
03670 #ifdef LOCAL_ROUTINES
03671    {
03672       DATABASE_HEADER *pheader;
03673       KEY *pkey;
03674       HNDLE hkeylink;
03675       char link_name[256];
03676 
03677       if (hDB > _database_entries || hDB <= 0) {
03678          cm_msg(MERROR, "db_get_key", "invalid database handle");
03679          return DB_INVALID_HANDLE;
03680       }
03681 
03682       if (!_database[hDB - 1].attached) {
03683          cm_msg(MERROR, "db_get_key", "invalid database handle");
03684          return DB_INVALID_HANDLE;
03685       }
03686 
03687       if (hKey < (int) sizeof(DATABASE_HEADER) && hKey != 0) {
03688          cm_msg(MERROR, "db_get_key", "invalid key handle");
03689          return DB_INVALID_HANDLE;
03690       }
03691 
03692       db_lock_database(hDB);
03693 
03694       pheader = _database[hDB - 1].database_header;
03695 
03696       if (!hKey)
03697          hKey = pheader->root_key;
03698 
03699       pkey = (KEY *) ((char *) pheader + hKey);
03700 
03701       /* check if hKey argument is correct */
03702       if (!db_validate_hkey(pheader, hKey)) {
03703          db_unlock_database(hDB);
03704          return DB_INVALID_HANDLE;
03705       }
03706 
03707       if (!pkey->type) {
03708          db_unlock_database(hDB);
03709          cm_msg(MERROR, "db_get_key", "invalid key type %d", pkey->type);
03710          return DB_INVALID_HANDLE;
03711       }
03712 
03713       /* check for link to array index */
03714       if (pkey->type == TID_LINK) {
03715          strlcpy(link_name, (char *) pheader + pkey->data, sizeof(link_name));
03716          if (strlen(link_name) > 0 && link_name[strlen(link_name) - 1] == ']') {
03717             db_unlock_database(hDB);
03718             if (strchr(link_name, '[') == NULL)
03719                return DB_INVALID_LINK;
03720             if (db_find_key(hDB, 0, link_name, &hkeylink) != DB_SUCCESS)
03721                return DB_INVALID_LINK;
03722             db_get_key(hDB, hkeylink, key);
03723             key->num_values = 1;        // fake number of values
03724             return DB_SUCCESS;
03725          }
03726       }
03727 
03728       memcpy(key, pkey, sizeof(KEY));
03729 
03730       db_unlock_database(hDB);
03731 
03732    }
03733 #endif                          /* LOCAL_ROUTINES */
03734 
03735    return DB_SUCCESS;
03736 }

INT 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:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Handle of key to operate on
name Key name
name_size Size of the give name (done with sizeof())
type Key type (see Midas Data Types).
num_values Number of values in key.
item_size Size of individual key value (used for strings)
Returns:
DB_SUCCESS, DB_INVALID_HANDLE

Definition at line 3868 of file odb.c.

Referenced by rpc_server_dispatch().

03869 {
03870    if (rpc_is_remote())
03871       return rpc_call(RPC_DB_GET_KEY_INFO, hDB, hKey, name, name_size, type, num_values, item_size);
03872 
03873 #ifdef LOCAL_ROUTINES
03874    {
03875       DATABASE_HEADER *pheader;
03876       KEY *pkey;
03877       KEYLIST *pkeylist;
03878 
03879       if (hDB > _database_entries || hDB <= 0) {
03880          cm_msg(MERROR, "db_get_key_info", "invalid database handle");
03881          return DB_INVALID_HANDLE;
03882       }
03883 
03884       if (!_database[hDB - 1].attached) {
03885          cm_msg(MERROR, "db_get_key_info", "invalid database handle");
03886          return DB_INVALID_HANDLE;
03887       }
03888 
03889       if (hKey < (int) sizeof(DATABASE_HEADER)) {
03890          cm_msg(MERROR, "db_get_key_info", "invalid key handle");
03891          return DB_INVALID_HANDLE;
03892       }
03893 
03894       db_lock_database(hDB);
03895 
03896       pheader = _database[hDB - 1].database_header;
03897       pkey = (KEY *) ((char *) pheader + hKey);
03898 
03899       /* check if hKey argument is correct */
03900       if (!db_validate_hkey(pheader, hKey)) {
03901          db_unlock_database(hDB);
03902          return DB_INVALID_HANDLE;
03903       }
03904 
03905       if ((INT) strlen(pkey->name) + 1 > name_size) {
03906          /* truncate name */
03907          memcpy(name, pkey->name, name_size - 1);
03908          name[name_size] = 0;
03909       } else
03910          strcpy(name, pkey->name);
03911 
03912       /* convert "root" to "/" */
03913       if (strcmp(name, "root") == 0)
03914          strcpy(name, "/");
03915 
03916       *type = pkey->type;
03917       *num_values = pkey->num_values;
03918       *item_size = pkey->item_size;
03919 
03920       if (pkey->type == TID_KEY) {
03921          pkeylist = (KEYLIST *) ((char *) pheader + pkey->data);
03922          *num_values = pkeylist->num_keys;
03923       }
03924 
03925       db_unlock_database(hDB);
03926    }
03927 #endif                          /* LOCAL_ROUTINES */
03928 
03929    return DB_SUCCESS;
03930 }

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

Get time when key was last modified

Parameters:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Handle of key to operate on
delta Seconds since last update
Returns:
DB_SUCCESS, DB_INVALID_HANDLE

Definition at line 3810 of file odb.c.

Referenced by print_key(), rpc_server_dispatch(), and scan_tree().

03811 {
03812    if (rpc_is_remote())
03813       return rpc_call(RPC_DB_GET_KEY_TIME, hDB, hKey, delta);
03814 
03815 #ifdef LOCAL_ROUTINES
03816    {
03817       DATABASE_HEADER *pheader;
03818       KEY *pkey;
03819 
03820       if (hDB > _database_entries || hDB <= 0) {
03821          cm_msg(MERROR, "db_get_key", "invalid database handle");
03822          return DB_INVALID_HANDLE;
03823       }
03824 
03825       if (!_database[hDB - 1].attached) {
03826          cm_msg(MERROR, "db_get_key", "invalid database handle");
03827          return DB_INVALID_HANDLE;
03828       }
03829 
03830       if (hKey < (int) sizeof(DATABASE_HEADER)) {
03831          cm_msg(MERROR, "db_get_key", "invalid key handle");
03832          return DB_INVALID_HANDLE;
03833       }
03834 
03835       db_lock_database(hDB);
03836 
03837       pheader = _database[hDB - 1].database_header;
03838       pkey = (KEY *) ((char *) pheader + hKey);
03839 
03840       /* check if hKey argument is correct */
03841       if (!db_validate_hkey(pheader, hKey)) {
03842          db_unlock_database(hDB);
03843          return DB_INVALID_HANDLE;
03844       }
03845 
03846       *delta = ss_time() - pkey->last_written;
03847 
03848       db_unlock_database(hDB);
03849 
03850    }
03851 #endif                          /* LOCAL_ROUTINES */
03852 
03853    return DB_SUCCESS;
03854 }

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

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

Parameters:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Handle for key where search starts, zero for root.
key Pointer to KEY stucture.
Returns:
DB_SUCCESS, DB_INVALID_HANDLE

Definition at line 3746 of file odb.c.

Referenced by cmd_dir(), command_loop(), db_copy(), db_save_xml_key(), rpc_server_dispatch(), set_key(), show_delete_page(), show_odb_page(), and show_start_page().

03747 {
03748    if (rpc_is_remote())
03749       return rpc_call(RPC_DB_GET_LINK, hDB, hKey, key);
03750 
03751 #ifdef LOCAL_ROUTINES
03752    {
03753       DATABASE_HEADER *pheader;
03754       KEY *pkey;
03755 
03756       if (hDB > _database_entries || hDB <= 0) {
03757          cm_msg(MERROR, "db_get_key", "invalid database handle");
03758          return DB_INVALID_HANDLE;
03759       }
03760 
03761       if (!_database[hDB - 1].attached) {
03762          cm_msg(MERROR, "db_get_key", "invalid database handle");
03763          return DB_INVALID_HANDLE;
03764       }
03765 
03766       if (hKey < (int) sizeof(DATABASE_HEADER) && hKey != 0) {
03767          cm_msg(MERROR, "db_get_key", "invalid key handle");
03768          return DB_INVALID_HANDLE;
03769       }
03770 
03771       db_lock_database(hDB);
03772 
03773       pheader = _database[hDB - 1].database_header;
03774 
03775       if (!hKey)
03776          hKey = pheader->root_key;
03777 
03778       pkey = (KEY *) ((char *) pheader + hKey);
03779 
03780       /* check if hKey argument is correct */
03781       if (!db_validate_hkey(pheader, hKey)) {
03782          db_unlock_database(hDB);
03783          return DB_INVALID_HANDLE;
03784       }
03785 
03786       if (!pkey->type) {
03787          db_unlock_database(hDB);
03788          cm_msg(MERROR, "db_get_key", "invalid key type %d", pkey->type);
03789          return DB_INVALID_HANDLE;
03790       }
03791 
03792       memcpy(key, pkey, sizeof(KEY));
03793 
03794       db_unlock_database(hDB);
03795 
03796    }
03797 #endif                          /* LOCAL_ROUTINES */
03798 
03799    return DB_SUCCESS;
03800 }

INT 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:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Handle for key where search starts, zero for root.
data Pointer to the return data.
buf_size Size of data buffer.
type Type of key, one of TID_xxx (see Midas Data Types).
Returns:
DB_SUCCESS, DB_INVALID_HANDLE, DB_TRUNCATED, DB_TYPE_MISMATCH

Definition at line 4306 of file odb.c.

Referenced by cmd_dir(), db_copy(), db_save_xml_key(), print_key(), rpc_server_dispatch(), and show_odb_page().

04307 {
04308    if (rpc_is_remote())
04309       return rpc_call(RPC_DB_GET_LINK_DATA, hDB, hKey, data, buf_size, type);
04310 
04311 #ifdef LOCAL_ROUTINES
04312    {
04313       DATABASE_HEADER *pheader;
04314       KEY *pkey;
04315 
04316       if (hDB > _database_entries || hDB <= 0) {
04317          cm_msg(MERROR, "db_get_data", "Invalid database handle");
04318          return DB_INVALID_HANDLE;
04319       }
04320 
04321       if (!_database[hDB - 1].attached) {
04322          cm_msg(MERROR, "db_get_data", "invalid database handle");
04323          return DB_INVALID_HANDLE;
04324       }
04325 
04326       if (hKey < (int) sizeof(DATABASE_HEADER)) {
04327          cm_msg(MERROR, "db_get_data", "invalid key handle");
04328          return DB_INVALID_HANDLE;
04329       }
04330 
04331       db_lock_database(hDB);
04332 
04333       pheader = _database[hDB - 1].database_header;
04334       pkey = (KEY *) ((char *) pheader + hKey);
04335 
04336       /* check if hKey argument is correct */
04337       if (!db_validate_hkey(pheader, hKey)) {
04338          db_unlock_database(hDB);
04339          return DB_INVALID_HANDLE;
04340       }
04341 
04342       /* check for read access */
04343       if (!(pkey->access_mode & MODE_READ)) {
04344          db_unlock_database(hDB);
04345          return DB_NO_ACCESS;
04346       }
04347 
04348       if (!pkey->type) {
04349          db_unlock_database(hDB);
04350          cm_msg(MERROR, "db_get_data", "invalid key type %d", pkey->type);
04351          return DB_INVALID_HANDLE;
04352       }
04353 
04354       if (pkey->type != type) {
04355          db_unlock_database(hDB);
04356          cm_msg(MERROR, "db_get_data", "\"%s\" is of type %s, not %s",
04357                 pkey->name, rpc_tid_name(pkey->type), rpc_tid_name(type));
04358          return DB_TYPE_MISMATCH;
04359       }
04360 
04361       /* keys cannot contain data */
04362       if (pkey->type == TID_KEY) {
04363          db_unlock_database(hDB);
04364          cm_msg(MERROR, "db_get_data", "Key cannot contain data");
04365          return DB_TYPE_MISMATCH;
04366       }
04367 
04368       /* check if key has data */
04369       if (pkey->data == 0) {
04370          memset(data, 0, *buf_size);
04371          *buf_size = 0;
04372          db_unlock_database(hDB);
04373          return DB_SUCCESS;
04374       }
04375 
04376       /* check if buffer is too small */
04377       if (pkey->num_values * pkey->item_size > *buf_size) {
04378          memcpy(data, (char *) pheader + pkey->data, *buf_size);
04379          db_unlock_database(hDB);
04380          cm_msg(MERROR, "db_get_data", "data for key \"%s\" truncated", pkey->name);
04381          return DB_TRUNCATED;
04382       }
04383 
04384       /* copy key data */
04385       memcpy(data, (char *) pheader + pkey->data, pkey->num_values * pkey->item_size);
04386       *buf_size = pkey->num_values * pkey->item_size;
04387 
04388       db_unlock_database(hDB);
04389 
04390    }
04391 #endif                          /* LOCAL_ROUTINES */
04392 
04393    return DB_SUCCESS;
04394 }

INT db_get_lock_cnt ( HNDLE  hDB  ) 

Definition at line 1497 of file odb.c.

01498 {
01499 #ifdef LOCAL_ROUTINES
01500 
01501    /* return zero if no ODB is open or we run remotely */
01502    if (_database_entries == 0)
01503       return 0;
01504 
01505    if (hDB > _database_entries || hDB <= 0) {
01506       cm_msg(MERROR, "db_lock_database", "invalid database handle, aborting...");
01507       abort();
01508       return DB_INVALID_HANDLE;
01509    }
01510 
01511    return _database[hDB - 1].lock_cnt;
01512 #else
01513    return 0;
01514 #endif
01515 }

INT 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;
} trigger_settings;
char *trigger_settings_str =
"[Settings]\n\
level1 = INT : 0\n\
level2 = INT : 0";

main()
{
  HNDLE hDB, hkey;
  INT   size;
  ...
  cm_get_experiment_database(&hDB, NULL);
  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);
  ...
}
Parameters:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Handle for key where search starts, zero for root.
data Pointer to the retrieved data.
buf_size Size of data structure, must be obtained via sizeof(RECORD-NAME).
align Byte 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 7486 of file odb.c.

Referenced by al_check(), al_reset_alarm(), al_trigger_alarm(), cm_transition1(), db_open_record(), db_update_record(), main(), register_equipment(), rpc_server_dispatch(), show_custom_gif(), show_status_page(), and tr_start().

07487 {
07488    if (rpc_is_remote()) {
07489       align = ss_get_struct_align();
07490       return rpc_call(RPC_DB_GET_RECORD, hDB, hKey, data, buf_size, align);
07491    }
07492 #ifdef LOCAL_ROUTINES
07493    {
07494       KEY key;
07495       INT convert_flags, status;
07496       INT total_size;
07497       void *pdata;
07498       char str[256];
07499 
07500       convert_flags = 0;
07501 
07502       if (!align)
07503          align = ss_get_struct_align();
07504       else
07505          /* only convert data if called remotely, as indicated by align != 0 */
07506       if (rpc_get_server_option(RPC_OSERVER_TYPE) != ST_REMOTE)
07507          convert_flags = rpc_get_server_option(RPC_CONVERT_FLAGS);
07508 
07509       /* check if key has subkeys */
07510       status = db_get_key(hDB, hKey, &key);
07511       if (status != DB_SUCCESS)
07512          return status;
07513 
07514       if (key.type != TID_KEY) {
07515          /* copy single key */
07516          if (key.item_size * key.num_values != *buf_size) {
07517             cm_msg(MERROR, "db_get_record", "struct size mismatch for \"%s\"", key.name);
07518             return DB_STRUCT_SIZE_MISMATCH;
07519          }
07520 
07521          db_get_data(hDB, hKey, data, buf_size, key.type);
07522 
07523          if (convert_flags) {
07524             if (key.num_values > 1)
07525                rpc_convert_data(data, key.type,
07526                                 RPC_OUTGOING | RPC_FIXARRAY, key.item_size * key.num_values, convert_flags);
07527             else
07528                rpc_convert_single(data, key.type, RPC_OUTGOING, convert_flags);
07529          }
07530 
07531          return DB_SUCCESS;
07532       }
07533 
07534       /* check record size */
07535       db_get_record_size(hDB, hKey, 0, &total_size);
07536       if (total_size != *buf_size) {
07537          db_get_path(hDB, hKey, str, sizeof(str));
07538          cm_msg(MERROR, "db_get_record",
07539                 "struct size mismatch for \"%s\" (expected size: %d, size in ODB: %d)", str, *buf_size, total_size);
07540          return DB_STRUCT_SIZE_MISMATCH;
07541       }
07542 
07543       /* get subkey data */
07544       pdata = data;
07545       total_size = 0;
07546 
07547       db_lock_database(hDB);
07548       db_recurse_record_tree(hDB, hKey, &pdata, &total_size, align, NULL, FALSE, convert_flags);
07549       db_unlock_database(hDB);
07550 
07551    }
07552 #endif                          /* LOCAL_ROUTINES */
07553 
07554    return DB_SUCCESS;
07555 }

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

Calculates the size of a record.

Parameters:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Handle for key where search starts, zero for root.
align Byte 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_size Size of record structure
Returns:
DB_SUCCESS, DB_INVALID_HANDLE, DB_TYPE_MISMATCH, DB_STRUCT_SIZE_MISMATCH, DB_NO_KEY

Definition at line 7400 of file odb.c.

Referenced by add_event(), command_loop(), db_get_record(), db_open_record(), db_set_record(), init_module_parameters(), log_history(), open_history(), rpc_server_dispatch(), and show_status_page().

07401 {
07402    if (rpc_is_remote()) {
07403       align = ss_get_struct_align();
07404       return rpc_call(RPC_DB_GET_RECORD_SIZE, hDB, hKey, align, buf_size);
07405    }
07406 #ifdef LOCAL_ROUTINES
07407    {
07408       KEY key;
07409       INT status, max_align;
07410 
07411       if (!align)
07412          align = ss_get_struct_align();
07413 
07414       /* check if key has subkeys */
07415       status = db_get_key(hDB, hKey, &key);
07416       if (status != DB_SUCCESS)
07417          return status;
07418 
07419       if (key.type != TID_KEY) {
07420          /* just a single key */
07421          *buf_size = key.item_size * key.num_values;
07422          return DB_SUCCESS;
07423       }
07424 
07425       db_lock_database(hDB);
07426 
07427       /* determine record size */
07428       *buf_size = max_align = 0;
07429       db_recurse_record_tree(hDB, hKey, NULL, buf_size, align, &max_align, 0, 0);
07430 
07431       /* correct for byte padding */
07432       *buf_size = VALIGN(*buf_size, max_align);
07433 
07434       db_unlock_database(hDB);
07435    }
07436 #endif                          /* LOCAL_ROUTINES */
07437 
07438    return DB_SUCCESS;
07439 }

INT 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_INT, 0);
Parameters:
hDB ODB handle obtained via cm_get_experiment_database().
hKeyRoot Handle for key where search starts, zero for root.
key_name Name of key to search, can contain directories.
data Address of data.
buf_size Maximum buffer size on input, number of written bytes on return.
type Type of key, one of TID_xxx (see Midas Data Types)
create If 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 3174 of file odb.c.

Referenced by add_event(), al_check(), al_trigger_alarm(), ana_end_of_run(), assemble_prompt(), bm_open_buffer(), book_ntuples(), bor(), cm_check_client(), cm_connect_experiment1(), cm_exist(), cm_msg_log(), cm_msg_log1(), cm_msg_retrieve(), cm_register_deferred_transition(), cm_set_client_info(), cm_shutdown(), cm_transition1(), command_loop(), create_experim_h(), db_get_event_definition(), do_jrpc_rev0(), el_submit(), evaluate_src(), export_hist(), gen_odb_attachment(), generate_hist_graph(), get_elog_url(), MidasHistory::GetEventsFromEquipment(), MidasHistory::hs_connect(), interprete(), lazy_main(), lazy_maintain_check(), lazy_select_purge(), lazy_settings_hotlink(), load_fragment(), log_callback(), log_generate_file_name(), log_write(), logger_init(), logger_root(), main(), odb_load(), odb_save(), open_history(), read_state(), register_equipment(), rpc_server_dispatch(), set_history_path(), show_alarm_page(), show_cnaf_page(), show_custom_gif(), show_custom_page(), show_elog_delete(), show_elog_new(), show_elog_page(), show_elog_query(), show_elog_submit_query(), show_form_query(), show_header(), show_hist_config_page(), show_hist_page(), show_messages_page(), show_programs_page(), show_rawfile(), show_start_page(), show_status_page(), start_the_run(), stop_the_run(), submit_elog(), tr_start(), tr_start_fal(), tr_stop(), and tr_stop_fal().

03175 {
03176    if (rpc_is_remote())
03177       return rpc_call(RPC_DB_GET_VALUE, hDB, hKeyRoot, key_name, data, buf_size, type, create);
03178 
03179 #ifdef LOCAL_ROUTINES
03180    {
03181       DATABASE_HEADER *pheader;
03182       HNDLE hkey;
03183       KEY *pkey;
03184       INT status, size, idx;
03185       char *p, path[256], keyname[256];
03186 
03187       if (hDB > _database_entries || hDB <= 0) {
03188          cm_msg(MERROR, "db_get_value", "invalid database handle");
03189          return DB_INVALID_HANDLE;
03190       }
03191 
03192       if (!_database[hDB - 1].attached) {
03193          cm_msg(MERROR, "db_get_value", "invalid database handle");
03194          return DB_INVALID_HANDLE;
03195       }
03196 
03197       /* check if key name contains index */
03198       strlcpy(keyname, key_name, sizeof(keyname));
03199       idx = -1;
03200       if (strchr(keyname, '[') && strchr(keyname, ']')) {
03201          for (p = strchr(keyname, '[') + 1; *p && *p != ']'; p++)
03202             if (!isdigit(*p))
03203                break;
03204 
03205          if (*p && *p == ']') {
03206             idx = atoi(strchr(keyname, '[') + 1);
03207             *strchr(keyname, '[') = 0;
03208          }
03209       }
03210 
03211       status = db_find_key(hDB, hKeyRoot, keyname, &hkey);
03212       if (status == DB_NO_KEY) {
03213          if (create) {
03214             db_create_key(hDB, hKeyRoot, keyname, type);
03215             status = db_find_key(hDB, hKeyRoot, keyname, &hkey);
03216             if (status != DB_SUCCESS)
03217                return status;
03218 
03219             /* get string size from data size */
03220             if (type == TID_STRING || type == TID_LINK)
03221                size = *buf_size;
03222             else
03223                size = rpc_tid_size(type);
03224 
03225             if (size == 0)
03226                return DB_TYPE_MISMATCH;
03227 
03228             /* set default value if key was created */
03229             status = db_set_value(hDB, hKeyRoot, keyname, data, *buf_size, *buf_size / size, type);
03230          } else
03231             return DB_NO_KEY;
03232       }
03233 
03234       if (status != DB_SUCCESS)
03235          return status;
03236 
03237       /* now lock database */
03238       db_lock_database(hDB);
03239       pheader = _database[hDB - 1].database_header;
03240 
03241       /* get address from handle */
03242       pkey = (KEY *) ((char *) pheader + hkey);
03243 
03244       /* check for correct type */
03245       if (pkey->type != (type)) {
03246          db_unlock_database(hDB);
03247          cm_msg(MERROR, "db_get_value", "\"%s\" is of type %s, not %s",
03248                 keyname, rpc_tid_name(pkey->type), rpc_tid_name(type));
03249          return DB_TYPE_MISMATCH;
03250       }
03251 
03252       /* check for read access */
03253       if (!(pkey->access_mode & MODE_READ)) {
03254          db_unlock_database(hDB);
03255          cm_msg(MERROR, "db_get_value", "%s has no read access", keyname);
03256          return DB_NO_ACCESS;
03257       }
03258 
03259       /* check if buffer is too small */
03260       if ((idx == -1 && pkey->num_values * pkey->item_size > *buf_size) || (idx != -1 && pkey->item_size > *buf_size)) {
03261          memcpy(data, (char *) pheader + pkey->data, *buf_size);
03262          db_unlock_database(hDB);
03263          db_get_path(hDB, hkey, path, sizeof(path));
03264          cm_msg(MERROR, "db_get_value", "buffer too small, data truncated for key \"%s\"", path);
03265          return DB_TRUNCATED;
03266       }
03267 
03268       /* check if index in boundaries */
03269       if (idx != -1 && idx >= pkey->num_values) {
03270          db_unlock_database(hDB);
03271          db_get_path(hDB, hkey, path, sizeof(path));
03272          cm_msg(MERROR, "db_get_value", "invalid index \"%d\" for key \"%s\"", idx, path);
03273          return DB_INVALID_PARAM;
03274       }
03275 
03276       /* copy key data */
03277       if (idx == -1) {
03278          memcpy(data, (char *) pheader + pkey->data, pkey->num_values * pkey->item_size);
03279          *buf_size = pkey->num_values * pkey->item_size;
03280       } else {
03281          memcpy(data, (char *) pheader + pkey->data + idx * pkey->item_size, pkey->item_size);
03282          *buf_size = pkey->item_size;
03283       }
03284 
03285       db_unlock_database(hDB);
03286    }
03287 #endif                          /* LOCAL_ROUTINES */
03288 
03289    return DB_SUCCESS;
03290 }

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

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:
hDB ODB handle obtained via cm_get_experiment_database().
hKeyRoot Handle for key where search starts, zero for root.
filename Filename of .ODB file.
bRemote If 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 5547 of file odb.c.

Referenced by command_loop(), load_parameters(), and rpc_server_dispatch().

05548 {
05549    struct stat stat_buf;
05550    INT hfile, size, n, i, status;
05551    char *buffer;
05552 
05553    if (rpc_is_remote() && bRemote)
05554       return rpc_call(RPC_DB_LOAD, hDB, hKeyRoot, filename);
05555 
05556    /* open file */
05557    hfile = open(filename, O_RDONLY | O_TEXT, 0644);
05558    if (hfile == -1) {
05559       cm_msg(MERROR, "db_load", "file \"%s\" not found", filename);
05560       return DB_FILE_ERROR;
05561    }
05562 
05563    /* allocate buffer with file size */
05564    fstat(hfile, &stat_buf);
05565    size = stat_buf.st_size;
05566    buffer = (char *) malloc(size + 1);
05567 
05568    if (buffer == NULL) {
05569       cm_msg(MERROR, "db_load", "cannot allocate ODB load buffer");
05570       close(hfile);
05571       return DB_NO_MEMORY;
05572    }
05573 
05574    n = 0;
05575 
05576    do {
05577       i = read(hfile, buffer + n, size - n);
05578       if (i <= 0)
05579          break;
05580       n += i;
05581    } while (TRUE);
05582 
05583    buffer[n] = 0;
05584 
05585    if (strncmp(buffer, "<?xml version=\"1.0\"", 19) == 0) {
05586       status = db_paste_xml(hDB, hKeyRoot, buffer);
05587       if (status != DB_SUCCESS)
05588          printf("Error in file \"%s\"\n", filename);
05589    } else
05590       status = db_paste(hDB, hKeyRoot, buffer);
05591 
05592    close(hfile);
05593    free(buffer);
05594 
05595    return status;
05596 }

INT db_lock_database ( HNDLE  hDB  ) 

Lock a database for exclusive access via system semaphore calls.

Parameters:
hDB Handle to the database to lock
Returns:
DB_SUCCESS, DB_INVALID_HANDLE, DB_TIMEOUT

Definition at line 1389 of file odb.c.

Referenced by cm_check_client(), cm_delete_client_info(), cm_get_watchdog_info(), cm_set_client_info(), cm_set_watchdog_params(), db_close_database(), db_create_key(), db_create_record(), db_delete_key1(), db_enum_key(), db_find_key(), db_get_data(), db_get_data_index(), db_get_key(), db_get_key_info(), db_get_key_time(), db_get_link(), db_get_link_data(), db_get_record(), db_get_record_size(), db_get_value(), db_open_database(), db_set_data(), db_set_data_index(), db_set_link_data(), db_set_link_data_index(), db_set_record(), db_set_value(), and log_system_history().

01390 {
01391 #ifdef LOCAL_ROUTINES
01392    int status;
01393    void *p;
01394 
01395 #ifdef CHECK_THREAD_ID
01396    if (_lock_tid == 0)
01397       _lock_tid = ss_gettid();
01398 
01399    assert(_lock_tid == ss_gettid());
01400 #endif
01401 
01402    if (hDB > _database_entries || hDB <= 0) {
01403       cm_msg(MERROR, "db_lock_database", "invalid database handle, aborting...");
01404       abort();
01405       return DB_INVALID_HANDLE;
01406    }
01407 
01408    if (_database[hDB - 1].protect && _database[hDB - 1].database_header != NULL) {
01409       cm_msg(MERROR, "db_lock_database", "internal error: DB already locked, aborting...");
01410       abort();
01411       return DB_NO_SEMAPHORE;
01412    }
01413 
01414    if (_database[hDB - 1].lock_cnt == 0) {
01415       /* wait max. 5 minutes for semaphore (required if locking process is being debugged) */
01416       status = ss_semaphore_wait_for(_database[hDB - 1].semaphore, 5 * 60 * 1000);
01417       if (status == SS_TIMEOUT) {
01418          cm_msg(MERROR, "db_lock_database", "timeout obtaining lock for database, exiting...");
01419          exit(1);
01420          return DB_TIMEOUT;
01421       }
01422       if (status != SS_SUCCESS) {
01423          cm_msg(MERROR, "db_lock_database", "cannot lock database, ss_semaphore_wait_for() status %d, aborting...", status);
01424          abort();
01425          return DB_NO_SEMAPHORE;
01426       }
01427    }
01428 
01429    _database[hDB - 1].lock_cnt++;
01430 
01431 #ifdef CHECK_LOCK_COUNT
01432    {
01433       char str[256];
01434 
01435       sprintf(str, "db_lock_database, lock_cnt=%d", _database[hDB - 1].lock_cnt);
01436       ss_stack_history_entry(str);
01437    }
01438 #endif
01439 
01440    if (_database[hDB - 1].protect) {
01441       if (_database[hDB - 1].database_header == NULL) {
01442          ss_shm_unprotect(_database[hDB - 1].shm_handle, &p);
01443          _database[hDB - 1].database_header = (DATABASE_HEADER *) p;
01444       }
01445    }
01446 #endif                          /* LOCAL_ROUTINES */
01447    return DB_SUCCESS;
01448 }

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

Open an online database

Parameters:
database_name Database name.
database_size Initial size of database if not existing
client_name Name of this application
hDB ODB 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 786 of file odb.c.

Referenced by cm_connect_experiment1(), and rpc_server_dispatch().

00787 {
00788    if (rpc_is_remote())
00789       return rpc_call(RPC_DB_OPEN_DATABASE, xdatabase_name, database_size, hDB, client_name);
00790 
00791 #ifdef LOCAL_ROUTINES
00792    {
00793       INT i, status;
00794       HNDLE handle;
00795       DATABASE_CLIENT *pclient;
00796       BOOL shm_created;
00797       HNDLE shm_handle;
00798       DATABASE_HEADER *pheader;
00799       KEY *pkey;
00800       KEYLIST *pkeylist;
00801       FREE_DESCRIP *pfree;
00802       BOOL call_watchdog;
00803       DWORD timeout;
00804       char database_name[NAME_LENGTH];
00805       void *p;
00806 
00807       /* restrict name length */
00808       strlcpy(database_name, xdatabase_name, NAME_LENGTH);
00809 
00810       if (database_size < 0 || database_size > 10E7) {
00811          cm_msg(MERROR, "db_open_database", "invalid database size");
00812          return DB_INVALID_PARAM;
00813       }
00814 
00815       if (strlen(client_name) >= NAME_LENGTH) {
00816          cm_msg(MERROR, "db_open_database", "client name \'%s\' is longer than %d characters", client_name, NAME_LENGTH-1);
00817          return DB_INVALID_PARAM;
00818       }
00819 
00820       if (strchr(client_name, '/') != NULL) {
00821          cm_msg(MERROR, "db_open_database", "client name \'%s\' should not contain the slash \'/\' character", client_name);
00822          return DB_INVALID_PARAM;
00823       }
00824 
00825       /* allocate new space for the new database descriptor */
00826       if (_database_entries == 0) {
00827          _database = (DATABASE *) malloc(sizeof(DATABASE));
00828          memset(_database, 0, sizeof(DATABASE));
00829          if (_database == NULL) {
00830             *hDB = 0;
00831             return DB_NO_MEMORY;
00832          }
00833 
00834          _database_entries = 1;
00835          i = 0;
00836       } else {
00837          /* check if database already open */
00838          for (i = 0; i < _database_entries; i++)
00839             if (_database[i].attached && equal_ustring(_database[i].name, database_name)) {
00840                /* check if database belongs to this thread */
00841                if (rpc_get_server_option(RPC_OSERVER_TYPE) == ST_MTHREAD) {
00842                   if (_database[i].index == ss_gettid()) {
00843                      *hDB = i + 1;
00844                      return DB_SUCCESS;
00845                   }
00846                } else {
00847                   *hDB = i + 1;
00848                   return DB_SUCCESS;
00849                }
00850             }
00851 
00852          /* check for a deleted entry */
00853          for (i = 0; i < _database_entries; i++)
00854             if (!_database[i].attached)
00855                break;
00856 
00857          /* if not found, create new one */
00858          if (i == _database_entries) {
00859             _database = (DATABASE *) realloc(_database, sizeof(DATABASE) * (_database_entries + 1));
00860             memset(&_database[_database_entries], 0, sizeof(DATABASE));
00861 
00862             _database_entries++;
00863             if (_database == NULL) {
00864                _database_entries--;
00865                *hDB = 0;
00866                return DB_NO_MEMORY;
00867             }
00868          }
00869       }
00870 
00871       handle = (HNDLE) i;
00872 
00873       /* open shared memory region */
00874       status = ss_shm_open(database_name,
00875                            sizeof(DATABASE_HEADER) + 2 * ALIGN8(database_size / 2), &p, &shm_handle, TRUE);
00876 
00877       _database[(INT) handle].database_header = (DATABASE_HEADER *) p;
00878       if (status == SS_NO_MEMORY || status == SS_FILE_ERROR) {
00879          *hDB = 0;
00880          return DB_INVALID_NAME;
00881       }
00882 
00883       /* shortcut to header */
00884       pheader = _database[handle].database_header;
00885 
00886       /* save name */
00887       strcpy(_database[handle].name, database_name);
00888 
00889       shm_created = (status == SS_CREATED);
00890 
00891       /* clear memeory for debugging */
00892       /* memset(pheader, 0, sizeof(DATABASE_HEADER) + 2*ALIGN8(database_size/2)); */
00893 
00894       if (shm_created && pheader->name[0] == 0) {
00895          /* setup header info if database was created */
00896          memset(pheader, 0, sizeof(DATABASE_HEADER) + 2 * ALIGN8(database_size / 2));
00897 
00898          strcpy(pheader->name, database_name);
00899          pheader->version = DATABASE_VERSION;
00900          pheader->key_size = ALIGN8(database_size / 2);
00901          pheader->data_size = ALIGN8(database_size / 2);
00902          pheader->root_key = sizeof(DATABASE_HEADER);
00903          pheader->first_free_key = sizeof(DATABASE_HEADER);
00904          pheader->first_free_data = sizeof(DATABASE_HEADER) + pheader->key_size;
00905 
00906          /* set up free list */
00907          pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_key);
00908          pfree->size = pheader->key_size;
00909          pfree->next_free = 0;
00910 
00911          pfree = (FREE_DESCRIP *) ((char *) pheader + pheader->first_free_data);
00912          pfree->size = pheader->data_size;
00913          pfree->next_free = 0;
00914 
00915          /* create root key */
00916          pkey = (KEY *) malloc_key(pheader, sizeof(KEY));
00917 
00918          /* set key properties */
00919          pkey->type = TID_KEY;
00920          pkey->num_values = 1;
00921          pkey->access_mode = MODE_READ | MODE_WRITE | MODE_DELETE;
00922          strcpy(pkey->name, "root");
00923          pkey->parent_keylist = 0;
00924 
00925          /* create keylist */
00926          pkeylist = (KEYLIST *) malloc_key(pheader, sizeof(KEYLIST));
00927 
00928          /* store keylist in data field */
00929          pkey->data = (POINTER_T) pkeylist - (POINTER_T) pheader;
00930          pkey->item_size = sizeof(KEYLIST);
00931          pkey->total_size = sizeof(KEYLIST);
00932 
00933          pkeylist->parent = (POINTER_T) pkey - (POINTER_T) pheader;
00934          pkeylist->num_keys = 0;
00935          pkeylist->first_key = 0;
00936       }
00937 
00938       /* check database version */
00939       if (pheader->version != DATABASE_VERSION) {
00940          cm_msg(MERROR, "db_open_database",
00941                 "Different database format: Shared memory is %d, program is %d", pheader->version, DATABASE_VERSION);
00942          return DB_VERSION_MISMATCH;
00943       }
00944 
00945       /* create semaphore for the database */
00946       status = ss_semaphore_create(database_name, &(_database[handle].semaphore));
00947       if (status != SS_SUCCESS && status != SS_CREATED) {
00948          *hDB = 0;
00949          return DB_NO_SEMAPHORE;
00950       }
00951       _database[handle].lock_cnt = 0;
00952 
00953       /* first lock database */
00954       status = db_lock_database(handle + 1);
00955       if (status != DB_SUCCESS)
00956          return status;
00957 
00958       /*
00959          Now we have a DATABASE_HEADER, so let's setup a CLIENT
00960          structure in that database. The information there can also
00961          be seen by other processes.
00962        */
00963 
00964       /*
00965          update the client count
00966        */
00967       pheader->num_clients = 0;
00968       pheader->max_client_index = 0;
00969       for (i = 0; i < MAX_CLIENTS; i++) {
00970          if (pheader->client[i].pid == 0)
00971             continue;
00972          pheader->num_clients++;
00973          pheader->max_client_index = i + 1;
00974       }
00975 
00976       /*fprintf(stderr,"num_clients: %d, max_client: %d\n",pheader->num_clients,pheader->max_client_index); */
00977 
00978       /*
00979          Look for empty client slot
00980        */
00981       for (i = 0; i < MAX_CLIENTS; i++)
00982          if (pheader->client[i].pid == 0)
00983             break;
00984 
00985       if (i == MAX_CLIENTS) {
00986          db_unlock_database(handle + 1);
00987          *hDB = 0;
00988          cm_msg(MERROR, "db_open_database", "maximum number of clients exceeded");
00989          return DB_NO_SLOT;
00990       }
00991 
00992       /* store slot index in _database structure */
00993       _database[handle].client_index = i;
00994 
00995       /*
00996          Save the index of the last client of that database so that later only
00997          the clients 0..max_client_index-1 have to be searched through.
00998        */
00999       pheader->num_clients++;
01000       if (i + 1 > pheader->max_client_index)
01001          pheader->max_client_index = i + 1;
01002 
01003       /* setup database header and client structure */
01004       pclient = &pheader->client[i];
01005 
01006       memset(pclient, 0, sizeof(DATABASE_CLIENT));
01007       /* use client name previously set by bm_set_name */
01008       strlcpy(pclient->name, client_name, sizeof(pclient->name));
01009       pclient->pid = ss_getpid();
01010       pclient->num_open_records = 0;
01011 
01012       ss_suspend_get_port(&pclient->port);
01013 
01014       pclient->last_activity = ss_millitime();
01015 
01016       cm_get_watchdog_params(&call_watchdog, &timeout);
01017       pclient->watchdog_timeout = timeout;
01018 
01019       /* check ODB for corruption */
01020       if (!db_validate_db(pheader)) {
01021          /* do not treat corrupted odb as a fatal error- allow the user
01022             to preceed at own risk- the database is already corrupted,
01023             so no further harm can possibly be made. */
01024          /*
01025             db_unlock_database(handle + 1);
01026             *hDB = 0;
01027             return DB_CORRUPTED;
01028           */
01029       }
01030 
01031       /* setup _database entry */
01032       _database[handle].database_data = _database[handle].database_header + 1;
01033       _database[handle].attached = TRUE;
01034       _database[handle].shm_handle = shm_handle;
01035       _database[handle].protect = FALSE;
01036 
01037       /* remember to which connection acutal buffer belongs */
01038       if (rpc_get_server_option(RPC_OSERVER_TYPE) == ST_SINGLE)
01039          _database[handle].index = rpc_get_server_acception();
01040       else
01041          _database[handle].index = ss_gettid();
01042 
01043       *hDB = (handle + 1);
01044 
01045       /* setup dispatcher for updated records */
01046       ss_suspend_set_dispatch(CH_IPC, 0, (int (*)(void)) cm_dispatch_ipc);
01047 
01048 
01049       /* remove dead clients */
01050 
01051 #ifdef OS_UNIX
01052 #ifdef ESRCH
01053       /* Only enable this for systems that define ESRCH and hope that
01054          they also support kill(pid,0) */
01055       for (i = 0; i < MAX_CLIENTS; i++) {
01056          int k;
01057 
01058          errno = 0;
01059          kill(pheader->client[i].pid, 0);
01060          if (errno == ESRCH) {
01061             cm_msg(MERROR, "db_open_database",
01062                    "Removing client \'%s\', pid %d, index %d because the pid no longer exists",
01063                    pheader->client[i].name, pheader->client[i].pid, i);
01064 
01065             /* decrement notify_count for open records and clear exclusive mode */
01066             for (k = 0; k < pheader->client[i].max_index; k++)
01067                if (pheader->client[i].open_record[k].handle) {
01068                   pkey = (KEY *) ((char *) pheader + pheader->client[i].open_record[k].handle);
01069                   if (pkey->notify_count > 0)
01070                      pkey->notify_count--;
01071 
01072                   if (pheader->client[i].open_record[k].access_mode & MODE_WRITE)
01073                      db_set_mode(handle + 1, pheader->client[i].open_record[k].handle,
01074                                  (WORD) (pkey->access_mode & ~MODE_EXCLUSIVE), 2);
01075                }
01076 
01077             /* clear entry from client structure in database header */
01078             memset(&(pheader->client[i]), 0, sizeof(DATABASE_CLIENT));
01079          }
01080       }
01081 #endif
01082 #endif
01083 
01084       db_unlock_database(handle + 1);
01085 
01086       if (shm_created)
01087          return DB_CREATED;
01088    }
01089 #endif                          /* LOCAL_ROUTINES */
01090 
01091    return DB_SUCCESS;
01092 }

INT 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 8463 of file odb.c.

Referenced by add_event(), analyzer_init(), book_ntuples(), cm_register_deferred_transition(), command_loop(), frontend_init(), init_module_parameters(), main(), mana_init(), open_history(), register_equipment(), register_requests(), and tr_start().

08465 {
08466    INT idx, status, size;
08467    KEY key;
08468    void *data;
08469    char str[256];
08470 
08471    /* allocate new space for the local record list */
08472    if (_record_list_entries == 0) {
08473       _record_list = (RECORD_LIST *) malloc(sizeof(RECORD_LIST));
08474       memset(_record_list, 0, sizeof(RECORD_LIST));
08475       if (_record_list == NULL) {
08476          cm_msg(MERROR, "db_open_record", "not enough memory");
08477          return DB_NO_MEMORY;
08478       }
08479 
08480       _record_list_entries = 1;
08481       idx = 0;
08482    } else {
08483       /* check for a deleted entry */
08484       for (idx = 0; idx < _record_list_entries; idx++)
08485          if (!_record_list[idx].handle)
08486             break;
08487 
08488       /* if not found, create new one */
08489       if (idx == _record_list_entries) {
08490          _record_list = (RECORD_LIST *) realloc(_record_list, sizeof(RECORD_LIST) * (_record_list_entries + 1));
08491          if (_record_list == NULL) {
08492             cm_msg(MERROR, "db_open_record", "not enough memory");
08493             return DB_NO_MEMORY;
08494          }
08495 
08496          memset(&_record_list[_record_list_entries], 0, sizeof(RECORD_LIST));
08497 
08498          _record_list_entries++;
08499       }
08500    }
08501 
08502    db_get_key(hDB, hKey, &key);
08503 
08504    /* check record size */
08505    status = db_get_record_size(hDB, hKey, 0, &size);
08506    if (status != DB_SUCCESS) {
08507       _record_list_entries--;
08508       cm_msg(MERROR, "db_open_record", "cannot get record size");
08509       return DB_NO_MEMORY;
08510    }
08511    if (size != rec_size && ptr != NULL) {
08512       _record_list_entries--;
08513       db_get_path(hDB, hKey, str, sizeof(str));
08514       cm_msg(MERROR, "db_open_record", "struct size mismatch for \"%s\" (%d instead of %d)", str, rec_size, size);
08515       return DB_STRUCT_SIZE_MISMATCH;
08516    }
08517 
08518    /* check for read access */
08519    if (((key.access_mode & MODE_EXCLUSIVE) && (access_mode & MODE_WRITE))
08520        || (!(key.access_mode & MODE_WRITE) && (access_mode & MODE_WRITE))
08521        || (!(key.access_mode & MODE_READ) && (access_mode & MODE_READ))) {
08522       _record_list_entries--;
08523       return DB_NO_ACCESS;
08524    }
08525 
08526    if (access_mode & MODE_ALLOC) {
08527       data = malloc(size);
08528       memset(data, 0, size);
08529 
08530       if (data == NULL) {
08531          _record_list_entries--;
08532          cm_msg(MERROR, "db_open_record", "not enough memory");
08533          return DB_NO_MEMORY;
08534       }
08535 
08536       *((void **) ptr) = data;
08537    } else
08538       data = ptr;
08539 
08540    /* copy record to local memory */
08541    if (access_mode & MODE_READ && data != NULL) {
08542       status = db_get_record(hDB, hKey, data, &size, 0);
08543       if (status != DB_SUCCESS) {
08544          _record_list_entries--;
08545          cm_msg(MERROR, "db_open_record", "cannot get record");
08546          return DB_NO_MEMORY;
08547       }
08548    }
08549 
08550    /* copy local record to ODB */
08551    if (access_mode & MODE_WRITE) {
08552       /* only write to ODB if not in MODE_ALLOC */
08553       if ((access_mode & MODE_ALLOC) == 0) {
08554          status = db_set_record(hDB, hKey, data, size, 0);
08555          if (status != DB_SUCCESS) {
08556             _record_list_entries--;
08557             cm_msg(MERROR, "db_open_record", "cannot set record");
08558             return DB_NO_MEMORY;
08559          }
08560       }
08561 
08562       /* init a local copy of the record */
08563       _record_list[idx].copy = malloc(size);
08564       if (_record_list[idx].copy == NULL) {
08565          cm_msg(MERROR, "db_open_record", "not enough memory");
08566          return DB_NO_MEMORY;
08567       }
08568 
08569       memcpy(_record_list[idx].copy, data, size);
08570    }
08571 
08572    /* initialize record list */
08573    _record_list[idx].handle = hKey;
08574    _record_list[idx].hDB = hDB;
08575    _record_list[idx].access_mode = access_mode;
08576    _record_list[idx].data = data;
08577    _record_list[idx].buf_size = size;
08578    _record_list[idx].dispatcher = dispatcher;
08579    _record_list[idx].info = info;
08580 
08581    /* add record entry in database structure */
08582    return db_add_open_record(hDB, hKey, (WORD) (access_mode & ~MODE_ALLOC));
08583 }

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

Copy an ODB subtree in ASCII format from a buffer

Parameters:
hDB ODB handle obtained via cm_get_experiment_database().
hKeyRoot Handle for key where search starts, zero for root.
buffer NULL-terminated buffer
Returns:
DB_SUCCESS, DB_TRUNCATED, DB_NO_MEMORY

Definition at line 5897 of file odb.c.

Referenced by command_loop(), db_create_record(), db_load(), and odb_load().

05898 {
05899    char line[MAX_STRING_LENGTH];
05900    char title[MAX_STRING_LENGTH];
05901    char key_name[MAX_STRING_LENGTH];
05902    char data_str[MAX_STRING_LENGTH + 50];
05903    char test_str[MAX_STRING_LENGTH];
05904    char *pc, *data;
05905    const char *pold;
05906    INT data_size;
05907    INT tid, i, j, n_data, string_length, status, size;
05908    HNDLE hKey;
05909    KEY root_key;
05910    BOOL multi_line;
05911 
05912    title[0] = 0;
05913    multi_line = FALSE;
05914 
05915    if (hKeyRoot == 0)
05916       db_find_key(hDB, hKeyRoot, "", &hKeyRoot);
05917 
05918    db_get_key(hDB, hKeyRoot, &root_key);
05919 
05920    /* initial data size */
05921    data_size = 1000;
05922    data = (char *) malloc(data_size);
05923    if (data == NULL) {
05924       cm_msg(MERROR, "db_paste", "cannot allocate data buffer");
05925       return DB_NO_MEMORY;
05926    }
05927 
05928    do {
05929       if (*buffer == 0)
05930          break;
05931 
05932       for (i = 0; *buffer != '\n' && *buffer && i < MAX_STRING_LENGTH; i++)
05933          line[i] = *buffer++;
05934 
05935       if (i == MAX_STRING_LENGTH) {
05936          cm_msg(MERROR, "db_paste", "line too long");
05937          free(data);
05938          return DB_TRUNCATED;
05939       }
05940 
05941       line[i] = 0;
05942       if (*buffer == '\n')
05943          buffer++;
05944 
05945       /* check if it is a section title */
05946       if (line[0] == '[') {
05947          /* extract title and append '/' */
05948          strlcpy(title, line + 1, sizeof(title));
05949          if (strchr(title, ']'))
05950             *strchr(title, ']') = 0;
05951          if (title[0] && title[strlen(title) - 1] != '/')
05952             strlcat(title, "/", sizeof(title));
05953       } else {
05954          /* valid data line if it includes '=' and no ';' */
05955          if (strchr(line, '=') && line[0] != ';') {
05956             /* copy type info and data */
05957             pc = strrchr(line, '=') + 1;
05958             while (strstr(line, ": [") != NULL && strstr(line, ": [") < pc) {
05959                pc -= 2;
05960                while (*pc != '=' && pc > line)
05961                   pc--;
05962                pc++;
05963             }
05964             while (*pc == ' ')
05965                pc++;
05966             strlcpy(data_str, pc, sizeof(data_str));
05967 
05968             /* extract key name */
05969             *strrchr(line, '=') = 0;
05970             while (strstr(line, ": [") && strchr(line, '='))
05971                *strrchr(line, '=') = 0;
05972 
05973             pc = &line[strlen(line) - 1];
05974             while (*pc == ' ')
05975                *pc-- = 0;
05976 
05977             key_name[0] = 0;
05978             if (title[0] != '.')
05979                strlcpy(key_name, title, sizeof(key_name));
05980 
05981             strlcat(key_name, line, sizeof(key_name));
05982 
05983             /* evaluate type info */
05984             strlcpy(line, data_str, sizeof(line));
05985             if (strchr(line, ' '))
05986                *strchr(line, ' ') = 0;
05987 
05988             n_data = 1;
05989             if (strchr(line, '[')) {
05990                n_data = atol(strchr(line, '[') + 1);
05991                *strchr(line, '[') = 0;
05992             }
05993 
05994             for (tid = 0; tid < TID_LAST; tid++)
05995                if (strcmp(tid_name[tid], line) == 0)
05996                   break;
05997 
05998             string_length = 0;
05999 
06000             if (tid == TID_LAST)
06001                cm_msg(MERROR, "db_paste", "found unknown data type \"%s\" in ODB file", line);
06002             else {
06003                /* skip type info */
06004                pc = data_str;
06005                while (*pc != ' ' && *pc)
06006                   pc++;
06007                while ((*pc == ' ' || *pc == ':') && *pc)
06008                   pc++;
06009                strlcpy(data_str, pc, sizeof(data_str));
06010 
06011                if (n_data > 1) {
06012                   data_str[0] = 0;
06013                   if (!*buffer)
06014                      break;
06015 
06016                   for (j = 0; *buffer != '\n' && *buffer; j++)
06017                      data_str[j] = *buffer++;
06018                   data_str[j] = 0;
06019                   if (*buffer == '\n')
06020                      buffer++;
06021                }
06022 
06023                for (i = 0; i < n_data; i++) {
06024                   /* strip trailing \n */
06025                   pc = &data_str[strlen(data_str) - 1];
06026                   while (*pc == '\n' || *pc == '\r')
06027                      *pc-- = 0;
06028 
06029                   if (tid == TID_STRING || tid == TID_LINK) {
06030                      if (!string_length) {
06031                         if (data_str[1] == '=')
06032                            string_length = -1;
06033                         else
06034                            string_length = atoi(data_str + 1);
06035                         if (string_length > MAX_STRING_LENGTH) {
06036                            string_length = MAX_STRING_LENGTH;
06037                            cm_msg(MERROR, "db_paste", "found string exceeding MAX_STRING_LENGTH");
06038                         }
06039                      }
06040 
06041                      if (string_length == -1) {
06042                         /* multi-line string */
06043                         if (strstr(buffer, "\n====#$@$#====\n") != NULL) {
06044                            string_length = (POINTER_T) strstr(buffer, "\n====#$@$#====\n") - (POINTER_T) buffer + 1;
06045 
06046                            if (string_length >= data_size) {
06047                               data_size += string_length + 100;
06048                               data = (char *) realloc(data, data_size);
06049                               if (data == NULL) {
06050                                  cm_msg(MERROR, "db_paste", "cannot allocate data buffer");
06051                                  return DB_NO_MEMORY;
06052                               }
06053                            }
06054 
06055                            memset(data, 0, data_size);
06056                            strncpy(data, buffer, string_length);
06057                            data[string_length - 1] = 0;
06058                            buffer = strstr(buffer, "\n====#$@$#====\n") + strlen("\n====#$@$#====\n");
06059                         } else
06060                            cm_msg(MERROR, "db_paste", "found multi-line string without termination sequence");
06061                      } else {
06062                         pc = data_str + 2;
06063                         while (*pc && *pc != ' ')
06064                            pc++;
06065                         while (*pc && *pc == ' ')
06066                            pc++;
06067 
06068                         /* limit string size */
06069                         *(pc + string_length - 1) = 0;
06070 
06071                         /* increase data buffer if necessary */
06072                         if (string_length * (i + 1) >= data_size) {
06073                            data_size += 1000;
06074                            data = (char *) realloc(data, data_size);
06075                            if (data == NULL) {
06076                               cm_msg(MERROR, "db_paste", "cannot allocate data buffer");
06077                               return DB_NO_MEMORY;
06078                            }
06079                         }
06080 
06081                         strlcpy(data + string_length * i, pc, string_length);
06082                      }
06083                   } else {
06084                      pc = data_str;
06085 
06086                      if (n_data > 1 && data_str[0] == '[') {
06087                         pc = strchr(data_str, ']') + 1;
06088                         while (*pc && *pc == ' ')
06089                            pc++;
06090                      }
06091 
06092                      db_sscanf(pc, data, &size, i, tid);
06093 
06094                      /* increase data buffer if necessary */
06095                      if (size * (i + 1) >= data_size) {
06096                         data_size += 1000;
06097                         data = (char *) realloc(data, data_size);
06098                         if (data == NULL) {
06099                            cm_msg(MERROR, "db_paste", "cannot allocate data buffer");
06100                            return DB_NO_MEMORY;
06101                         }
06102                      }
06103 
06104                   }
06105 
06106                   if (i < n_data - 1) {
06107                      data_str[0] = 0;
06108                      if (!*buffer)
06109                         break;
06110 
06111                      pold = buffer;
06112 
06113                      for (j = 0; *buffer != '\n' && *buffer; j++)
06114                         data_str[j] = *buffer++;
06115                      data_str[j] = 0;
06116                      if (*buffer == '\n')
06117                         buffer++;
06118 
06119                      /* test if valid data */
06120                      if (tid != TID_STRING && tid != TID_LINK) {
06121                         if (data_str[0] == 0 || (strchr(data_str, '=')
06122                                                  && strchr(data_str, ':')))
06123                            buffer = pold;
06124                      }
06125                   }
06126                }
06127 
06128                /* skip system client entries */
06129                strcpy(test_str, key_name);
06130                test_str[15] = 0;
06131 
06132                if (!equal_ustring(test_str, "/System/Clients")) {
06133                   if (root_key.type != TID_KEY) {
06134                      /* root key is destination key */
06135                      hKey = hKeyRoot;
06136                   } else {
06137                      /* create key and set value */
06138                      if (key_name[0] == '/') {
06139                         status = db_find_link(hDB, 0, key_name, &hKey);
06140                         if (status == DB_NO_KEY) {
06141                            db_create_key(hDB, 0, key_name, tid);
06142                            status = db_find_link(hDB, 0, key_name, &hKey);
06143                         }
06144                      } else {
06145                         status = db_find_link(hDB, hKeyRoot, key_name, &hKey);
06146                         if (status == DB_NO_KEY) {
06147                            db_create_key(hDB, hKeyRoot, key_name, tid);
06148                            status = db_find_link(hDB, hKeyRoot, key_name, &hKey);
06149                         }
06150                      }
06151                   }
06152 
06153                   /* set key data if created sucessfully */
06154                   if (hKey) {
06155                      if (tid == TID_STRING || tid == TID_LINK)
06156                         db_set_link_data(hDB, hKey, data, string_length * n_data, n_data, tid);
06157                      else
06158                         db_set_link_data(hDB, hKey, data, rpc_tid_size(tid) * n_data, n_data, tid);
06159                   }
06160                }
06161             }
06162          }
06163       }
06164    } while (TRUE);
06165 
06166    free(data);
06167    return DB_SUCCESS;
06168 }

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

Definition at line 6174 of file odb.c.

Referenced by db_paste_xml().

06175 {
06176    char type[256], data[256], test_str[256], buf[10000];
06177    int i, status, size, tid, num_values;
06178    HNDLE hKey;
06179    PMXML_NODE child;
06180 
06181    if (strcmp(mxml_get_name(node), "odb") == 0) {
06182       for (i = 0; i < mxml_get_number_of_children(node); i++) {
06183          status = db_paste_node(hDB, hKeyRoot, mxml_subnode(node, i));
06184          if (status != DB_SUCCESS)
06185             return status;
06186       }
06187    } else if (strcmp(mxml_get_name(node), "dir") == 0) {
06188       status = db_find_link(hDB, hKeyRoot, mxml_get_attribute(node, "name"), &hKey);
06189 
06190       /* skip system client entries */
06191       strlcpy(test_str, mxml_get_attribute(node, "name"), sizeof(test_str));
06192       test_str[15] = 0;
06193       if (equal_ustring(test_str, "/System/Clients"))
06194          return DB_SUCCESS;
06195 
06196       if (status == DB_NO_KEY) {
06197          status = db_create_key(hDB, hKeyRoot, mxml_get_attribute(node, "name"), TID_KEY);
06198          if (status == DB_NO_ACCESS)
06199             return DB_SUCCESS;  /* key or tree is locked, just skip it */
06200 
06201          if (status != DB_SUCCESS && status != DB_KEY_EXIST) {
06202             cm_msg(MERROR, "db_paste_node",
06203                    "cannot create key \"%s\" in ODB, status = %d", mxml_get_attribute(node, "name"), status);
06204             return status;
06205          }
06206          status = db_find_link(hDB, hKeyRoot, mxml_get_attribute(node, "name"), &hKey);
06207          if (status != DB_SUCCESS) {
06208             cm_msg(MERROR, "db_paste_node", "cannot find key \"%s\" in ODB", mxml_get_attribute(node, "name"));
06209             return status;
06210          }
06211       }
06212 
06213       db_get_path(hDB, hKey, data, sizeof(data));
06214       if (strncmp(data, "/System/Clients", 15) != 0) {
06215          for (i = 0; i < mxml_get_number_of_children(node); i++) {
06216             status = db_paste_node(hDB, hKey, mxml_subnode(node, i));
06217             if (status != DB_SUCCESS)
06218                return status;
06219          }
06220       }
06221    } else if (strcmp(mxml_get_name(node), "key") == 0 || strcmp(mxml_get_name(node), "keyarray") == 0) {
06222 
06223       if (strcmp(mxml_get_name(node), "keyarray") == 0)
06224          num_values = atoi(mxml_get_attribute(node, "num_values"));
06225       else
06226          num_values = 0;
06227 
06228       if (mxml_get_attribute(node, "type") == NULL) {
06229          cm_msg(MERROR, "db_paste_node", "found key \"%s\" with no type in XML data", mxml_get_name(node));
06230          return DB_TYPE_MISMATCH;
06231       }
06232 
06233       strlcpy(type, mxml_get_attribute(node, "type"), sizeof(type));
06234       for (tid = 0; tid < TID_LAST; tid++)
06235          if (strcmp(tid_name[tid], type) == 0)
06236             break;
06237       if (tid == TID_LAST) {
06238          cm_msg(MERROR, "db_paste_node", "found unknown data type \"%s\" in XML data", type);
06239          return DB_TYPE_MISMATCH;
06240       }
06241 
06242       status = db_find_link(hDB, hKeyRoot, mxml_get_attribute(node, "name"), &hKey);
06243       if (status == DB_NO_KEY) {
06244          status = db_create_key(hDB, hKeyRoot, mxml_get_attribute(node, "name"), tid);
06245          if (status == DB_NO_ACCESS)
06246             return DB_SUCCESS;  /* key or tree is locked, just skip it */
06247 
06248          if (status != DB_SUCCESS) {
06249             cm_msg(MERROR, "db_paste_node",
06250                    "cannot create key \"%s\" in ODB, status = %d", mxml_get_attribute(node, "name"), status);
06251             return status;
06252          }
06253          status = db_find_link(hDB, hKeyRoot, mxml_get_attribute(node, "name"), &hKey);
06254          if (status != DB_SUCCESS) {
06255             cm_msg(MERROR, "db_paste_node",
06256                    "cannot find key \"%s\" in ODB, status = %d", mxml_get_attribute(node, "name"));
06257             return status;
06258          }
06259       }
06260 
06261       if (num_values) {
06262          /* evaluate array */
06263          for (i = 0; i < mxml_get_number_of_children(node); i++) {
06264             child = mxml_subnode(node, i);
06265             if (tid == TID_STRING || tid == TID_LINK) {
06266                size = atoi(mxml_get_attribute(node, "size"));
06267                if (mxml_get_value(child) == NULL)
06268                   db_set_data_index(hDB, hKey, "", size, i, tid);
06269                else {
06270                   strlcpy(buf, mxml_get_value(child), sizeof(buf));
06271                   db_set_data_index(hDB, hKey, buf, size, i, tid);
06272                }
06273             } else {
06274                db_sscanf(mxml_get_value(child), data, &size, 0, tid);
06275                db_set_data_index(hDB, hKey, data, rpc_tid_size(tid), i, tid);
06276             }
06277          }
06278 
06279       } else {                  /* single value */
06280          if (tid == TID_STRING || tid == TID_LINK) {
06281             size = atoi(mxml_get_attribute(node, "size"));
06282             if (mxml_get_value(node) == NULL)
06283                db_set_data(hDB, hKey, "", size, 1, tid);
06284             else
06285                db_set_data(hDB, hKey, mxml_get_value(node), size, 1, tid);
06286          } else {
06287             db_sscanf(mxml_get_value(node), data, &size, 0, tid);
06288             db_set_data(hDB, hKey, data, rpc_tid_size(tid), 1, tid);
06289          }
06290       }
06291    }
06292 
06293    return DB_SUCCESS;
06294 }

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

Paste an ODB subtree in XML format from a buffer

Parameters:
hDB ODB handle obtained via cm_get_experiment_database().
hKeyRoot Handle for key where search starts, zero for root.
buffer NULL-terminated buffer
Returns:
DB_SUCCESS, DB_INVALID_PARAM, DB_NO_MEMORY, DB_TYPE_MISMATCH

Definition at line 6304 of file odb.c.

Referenced by db_load(), and odb_load().

06305 {
06306    char error[256];
06307    INT status;
06308    PMXML_NODE tree, node;
06309 
06310    if (hKeyRoot == 0)
06311       db_find_key(hDB, hKeyRoot, "", &hKeyRoot);
06312 
06313    /* parse XML buffer */
06314    tree = mxml_parse_buffer(buffer, error, sizeof(error));
06315    if (tree == NULL) {
06316       puts(error);
06317       return DB_TYPE_MISMATCH;
06318    }
06319 
06320    node = mxml_find_node(tree, "odb");
06321    if (node == NULL) {
06322       puts("Cannot find element \"odb\" in XML data");
06323       return DB_TYPE_MISMATCH;
06324    }
06325 
06326    status = db_paste_node(hDB, hKeyRoot, node);
06327 
06328    mxml_free_tree(tree);
06329 
06330    return status;
06331 }

INT db_protect_database ( HNDLE  hDB  ) 

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

Parameters:
hDB ODB handle obtained via cm_get_experiment_database().
Returns:
DB_SUCCESS, DB_INVALID_HANDLE

Definition at line 1523 of file odb.c.

Referenced by main().

01524 {
01525 #ifdef LOCAL_ROUTINES
01526    if (hDB > _database_entries || hDB <= 0) {
01527       cm_msg(MERROR, "db_unlock_database", "invalid database handle");
01528       return DB_INVALID_HANDLE;
01529    }
01530 
01531    _database[hDB - 1].protect = TRUE;
01532    ss_shm_protect(_database[hDB - 1].shm_handle, _database[hDB - 1].database_header);
01533    _database[hDB - 1].database_header = NULL;
01534 #endif                          /* LOCAL_ROUTINES */
01535    return DB_SUCCESS;
01536 }

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

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:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Handle for key where search starts, zero for root.
filename Filename of .ODB file.
bRemote Flag for saving database on remote server.
Returns:
DB_SUCCESS, DB_FILE_ERROR

Definition at line 6517 of file odb.c.

Referenced by command_loop(), lazy_main(), odb_save(), and rpc_server_dispatch().

06518 {
06519    if (rpc_is_remote() && bRemote)
06520       return rpc_call(RPC_DB_SAVE, hDB, hKey, filename, bRemote);
06521 
06522 #ifdef LOCAL_ROUTINES
06523    {
06524       INT hfile, size, buffer_size, n, status;
06525       char *buffer, path[256];
06526 
06527       /* open file */
06528       hfile = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_TEXT, 0644);
06529       if (hfile == -1) {
06530          cm_msg(MERROR, "db_save", "Cannot open file \"%s\"", filename);
06531          return DB_FILE_ERROR;
06532       }
06533 
06534       db_get_path(hDB, hKey, path, sizeof(path));
06535 
06536       buffer_size = 10000;
06537       do {
06538          buffer = (char *) malloc(buffer_size);
06539          if (buffer == NULL) {
06540             cm_msg(MERROR, "db_save", "cannot allocate ODB dump buffer");
06541             break;
06542          }
06543 
06544          size = buffer_size;
06545          status = db_copy(hDB, hKey, buffer, &size, path);
06546          if (status != DB_TRUNCATED) {
06547             n = write(hfile, buffer, buffer_size - size);
06548             free(buffer);
06549 
06550             if (n != buffer_size - size) {
06551                cm_msg(MERROR, "db_save", "cannot save .ODB file");
06552                close(hfile);
06553                return DB_FILE_ERROR;
06554             }
06555             break;
06556          }
06557 
06558          /* increase buffer size if truncated */
06559          free(buffer);
06560          buffer_size *= 2;
06561       } while (1);
06562 
06563       close(hfile);
06564 
06565    }
06566 #endif                          /* LOCAL_ROUTINES */
06567 
06568    return DB_SUCCESS;
06569 }

INT 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:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Handle for key where search starts, zero for root.
file_name Filename of .ODB file.
struct_name Name of structure. If struct_name == NULL, the name of the key is used.
append If TRUE, append to end of existing file
Returns:
DB_SUCCESS, DB_INVALID_HANDLE, DB_FILE_ERROR

Definition at line 6771 of file odb.c.

Referenced by command_loop(), and create_experim_h().

06772 {
06773    KEY key;
06774    char str[100], line[100];
06775    INT status, i, fh;
06776 
06777    /* open file */
06778    fh = open(file_name, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC), 0644);
06779 
06780    if (fh == -1) {
06781       cm_msg(MERROR, "db_save_struct", "Cannot open file\"%s\"", file_name);
06782       return DB_FILE_ERROR;
06783    }
06784 
06785    status = db_get_key(hDB, hKey, &key);
06786    if (status != DB_SUCCESS) {
06787       cm_msg(MERROR, "db_save_struct", "cannot find key");
06788       return DB_INVALID_HANDLE;
06789    }
06790 
06791    sprintf(line, "typedef struct {\n");
06792    write(fh, line, strlen(line));
06793    db_save_tree_struct(hDB, hKey, fh, 0);
06794 
06795    if (struct_name && struct_name[0])
06796       strcpy(str, struct_name);
06797    else
06798       strcpy(str, key.name);
06799 
06800    name2c(str);
06801    for (i = 0; i < (int) strlen(str); i++)
06802       str[i] = (char) toupper(str[i]);
06803 
06804    sprintf(line, "} %s;\n\n", str);
06805    write(fh, line, strlen(line));
06806 
06807    close(fh);
06808 
06809    return DB_SUCCESS;
06810 }

INT 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:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Handle for key where search starts, zero for root.
filename Filename of .XML file.
Returns:
DB_SUCCESS, DB_FILE_ERROR

Definition at line 6719 of file odb.c.

Referenced by command_loop(), and odb_save().

06720 {
06721 #ifdef LOCAL_ROUTINES
06722    {
06723       INT status;
06724       char str[256];
06725       MXML_WRITER *writer;
06726 
06727       /* open file */
06728       writer = mxml_open_file(filename);
06729       if (writer == NULL) {
06730          cm_msg(MERROR, "db_save_xml", "Cannot open file \"%s\"", filename);
06731          return DB_FILE_ERROR;
06732       }
06733 
06734       db_get_path(hDB, hKey, str, sizeof(str));
06735 
06736       /* write XML header */
06737       mxml_start_element(writer, "odb");
06738       mxml_write_attribute(writer, "root", str);
06739       mxml_write_attribute(writer, "filename", filename);
06740       mxml_write_attribute(writer, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
06741 
06742       if (getenv("MIDASSYS"))
06743          strcpy(str, getenv("MIDASSYS"));
06744       else
06745          strcpy(str, "");
06746       strcat(str, DIR_SEPARATOR_STR);
06747       strcat(str, "odb.xsd");
06748       mxml_write_attribute(writer, "xsi:noNamespaceSchemaLocation", str);
06749 
06750       status = db_save_xml_key(hDB, hKey, 0, writer);
06751 
06752       mxml_end_element(writer); // "odb"
06753       mxml_close_file(writer);
06754    }
06755 #endif                          /* LOCAL_ROUTINES */
06756 
06757    return DB_SUCCESS;
06758 }

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

Definition at line 6616 of file odb.c.

Referenced by db_copy_xml(), and db_save_xml().

06617 {
06618    INT i, idx, size, status;
06619    char str[MAX_STRING_LENGTH * 2], *data;
06620    HNDLE hSubkey;
06621    KEY key;
06622 
06623    status = db_get_link(hDB, hKey, &key);
06624    if (status != DB_SUCCESS)
06625       return status;
06626 
06627    if (key.type == TID_KEY) {
06628 
06629       /* save opening tag for subtree */
06630 
06631       if (level > 0) {
06632          mxml_start_element(writer, "dir");
06633          mxml_write_attribute(writer, "name", key.name);
06634       }
06635 
06636       for (idx = 0;; idx++) {
06637          db_enum_link(hDB, hKey, idx, &hSubkey);
06638 
06639          if (!hSubkey)
06640             break;
06641 
06642          /* save subtree */
06643          status = db_save_xml_key(hDB, hSubkey, level + 1, writer);
06644          if (status != DB_SUCCESS)
06645             return status;
06646       }
06647 
06648       /* save closing tag for subtree */
06649       if (level > 0)
06650          mxml_end_element(writer);
06651 
06652    } else {
06653 
06654       /* save key value */
06655 
06656       if (key.num_values > 1)
06657          mxml_start_element(writer, "keyarray");
06658       else
06659          mxml_start_element(writer, "key");
06660       mxml_write_attribute(writer, "name", key.name);
06661       mxml_write_attribute(writer, "type", rpc_tid_name(key.type));
06662 
06663       if (key.type == TID_STRING || key.type == TID_LINK) {
06664          sprintf(str, "%d", key.item_size);
06665          mxml_write_attribute(writer, "size", str);
06666       }
06667 
06668       if (key.num_values > 1) {
06669          sprintf(str, "%d", key.num_values);
06670          mxml_write_attribute(writer, "num_values", str);
06671       }
06672 
06673       size = key.total_size;
06674       data = (char *) malloc(size);
06675       if (data == NULL) {
06676          cm_msg(MERROR, "db_save_xml_key", "cannot allocate data buffer");
06677          return DB_NO_MEMORY;
06678       }
06679 
06680       db_get_link_data(hDB, hKey, data, &size, key.type);
06681 
06682       if (key.num_values == 1) {
06683 
06684          db_sprintf(str, data, key.item_size, 0, key.type);
06685          mxml_write_value(writer, str);
06686          mxml_end_element(writer);
06687 
06688       } else {                  /* array of values */
06689 
06690          for (i = 0; i < key.num_values; i++) {
06691 
06692             mxml_start_element(writer, "value");
06693             db_sprintf(str, data, key.item_size, i, key.type);
06694             mxml_write_value(writer, str);
06695             mxml_end_element(writer);
06696          }
06697 
06698          mxml_end_element(writer);      /* keyarray */
06699       }
06700 
06701       free(data);
06702    }
06703 
06704    return DB_SUCCESS;
06705 }

INT 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 }

HNDLE hDB, hKey;

// Main
int main(unsigned int argc,char **argv)
{
  char      host_name[HOST_NAME_LENGTH];
  char      expt_name[HOST_NAME_LENGTH];
  INT       lastnumber, status, msg;
  BOOL      debug=FALSE;
  char      i, ch;
  DWORD     update_time, mainlast_time;
  MY_STATISTICS (my_stat);

  // set default
  host_name[0] = 0;
  expt_name[0] = 0;

  // get default
  cm_get_environment(host_name, sizeof(host_name), expt_name, sizeof(expt_name));

  // get parameters
  for (i=1 ; i<argc ; i++)
  {
    if (argv[i][0] == '-' && argv[i][1] == 'd')
      debug = TRUE;
    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
    {
   usage:
      printf("usage: dbchange [-h <Hostname>] [-e <Experiment>]\n");
      return 0;
    }
  }

  // connect to experiment
  status = cm_connect_experiment(host_name, expt_name, "dbchange", 0);
  if (status != CM_SUCCESS)
    return 1;

  // Connect to DB
  cm_get_experiment_database(&hDB, &hKey);

  // Create a default structure in ODB
  db_create_record(hDB, 0, "My statistics", strcomb(my_stat));

  // 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);
  if (status != DB_SUCCESS)
  {
    cm_msg(MERROR, "mychange", "cannot open My statistics record");
    goto error;
  }

  // initialize ss_getchar()
  ss_getchar(0);

  // 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:
  cm_disconnect_experiment();
  return 1;
}
//-------- EOF dbchange.c
Returns:
DB_SUCCESS

Definition at line 8870 of file odb.c.

Referenced by lazy_statistics_update(), main(), scan_fragment(), and update_stats().

08871 {
08872    INT i;
08873 
08874    for (i = 0; i < _record_list_entries; i++)
08875       if (_record_list[i].access_mode & MODE_WRITE) {
08876          if (memcmp(_record_list[i].copy, _record_list[i].data, _record_list[i].buf_size) != 0) {
08877             /* switch to fast TCP mode temporarily */
08878             if (rpc_is_remote())
08879                rpc_set_option(-1, RPC_OTRANSPORT, RPC_FTCP);
08880             db_set_record(_record_list[i].hDB,
08881                           _record_list[i].handle, _record_list[i].data, _record_list[i].buf_size, 0);
08882             if (rpc_is_remote())
08883                rpc_set_option(-1, RPC_OTRANSPORT, RPC_TCP);
08884             memcpy(_record_list[i].copy, _record_list[i].data, _record_list[i].buf_size);
08885          }
08886       }
08887 
08888    return DB_SUCCESS;
08889 }

INT 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;
 INT   run_number;
 // get key handle for run number
 db_find_key(hDB, 0, "/Runinfo/Run number", &hkey);
 // set run number
 db_set_data(hDB, hkey, &run_number, sizeof(run_number),TID_INT);
Parameters:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Handle for key where search starts, zero for root.
data Buffer from which data gets copied to.
buf_size Size of data buffer.
num_values Number of data values (for arrays).
type Type of key, one of TID_xxx (see Midas Data Types).
Returns:
DB_SUCCESS, DB_INVALID_HANDLE, DB_TRUNCATED

Definition at line 4654 of file odb.c.

Referenced by add_event(), command_loop(), db_paste_node(), db_set_record(), rpc_server_dispatch(), show_create_page(), show_custom_page(), show_elog_page(), show_hist_page(), update_odb(), and write_event_odb().

04655 {
04656    if (rpc_is_remote())
04657       return rpc_call(RPC_DB_SET_DATA, hDB, hKey, data, buf_size, num_values, type);
04658 
04659 #ifdef LOCAL_ROUTINES
04660    {
04661       DATABASE_HEADER *pheader;
04662       KEY *pkey;
04663       HNDLE hkeylink;
04664       int link_idx;
04665       char link_name[256];
04666 
04667       if (hDB > _database_entries || hDB <= 0) {
04668          cm_msg(MERROR, "db_set_data", "invalid database handle");
04669          return DB_INVALID_HANDLE;
04670       }
04671 
04672       if (!_database[hDB - 1].attached) {
04673          cm_msg(MERROR, "db_set_data", "invalid database handle");
04674          return DB_INVALID_HANDLE;
04675       }
04676 
04677       if (hKey < (int) sizeof(DATABASE_HEADER)) {
04678          cm_msg(MERROR, "db_set_data", "invalid key handle");
04679          return DB_INVALID_HANDLE;
04680       }
04681 
04682       if (num_values == 0)
04683          return DB_INVALID_PARAM;
04684 
04685       db_lock_database(hDB);
04686 
04687       pheader = _database[hDB - 1].database_header;
04688       pkey = (KEY *) ((char *) pheader + hKey);
04689 
04690       /* check if hKey argument is correct */
04691       if (!db_validate_hkey(pheader, hKey)) {
04692          db_unlock_database(hDB);
04693          return DB_INVALID_HANDLE;
04694       }
04695 
04696       /* check for write access */
04697       if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
04698          db_unlock_database(hDB);
04699          return DB_NO_ACCESS;
04700       }
04701 
04702       /* check for link to array index */
04703       if (pkey->type == TID_LINK) {
04704          strlcpy(link_name, (char *) pheader + pkey->data, sizeof(link_name));
04705          if (strlen(link_name) > 0 && link_name[strlen(link_name) - 1] == ']') {
04706             db_unlock_database(hDB);
04707             if (strchr(link_name, '[') == NULL)
04708                return DB_INVALID_LINK;
04709             link_idx = atoi(strchr(link_name, '[') + 1);
04710             *strchr(link_name, '[') = 0;
04711             if (db_find_key(hDB, 0, link_name, &hkeylink) != DB_SUCCESS)
04712                return DB_INVALID_LINK;
04713             return db_set_data_index(hDB, hkeylink, data, buf_size, link_idx, type);
04714          }
04715       }
04716 
04717       if (pkey->type != type) {
04718          db_unlock_database(hDB);
04719          cm_msg(MERROR, "db_set_data", "\"%s\" is of type %s, not %s",
04720                 pkey->name, rpc_tid_name(pkey->type), rpc_tid_name(type));
04721          return DB_TYPE_MISMATCH;
04722       }
04723 
04724       /* keys cannot contain data */
04725       if (pkey->type == TID_KEY) {
04726          db_unlock_database(hDB);
04727          cm_msg(MERROR, "db_set_data", "Key cannot contain data");
04728          return DB_TYPE_MISMATCH;
04729       }
04730 
04731       /* if no buf_size given (Java!), calculate it */
04732       if (buf_size == 0)
04733          buf_size = pkey->item_size * num_values;
04734 
04735       /* resize data size if necessary */
04736       if (pkey->total_size != buf_size) {
04737          pkey->data = (POINTER_T) realloc_data(pheader, (char *) pheader + pkey->data, pkey->total_size, buf_size);
04738 
04739          if (pkey->data == 0) {
04740             db_unlock_database(hDB);
04741             cm_msg(MERROR, "db_set_data", "online database full");
04742             return DB_FULL;
04743          }
04744 
04745          pkey->data -= (POINTER_T) pheader;
04746          pkey->total_size = buf_size;
04747       }
04748 
04749       /* set number of values */
04750       pkey->num_values = num_values;
04751       if (num_values)
04752          pkey->item_size = buf_size / num_values;
04753 
04754       /* copy data */
04755       memcpy((char *) pheader + pkey->data, data, buf_size);
04756 
04757       /* update time */
04758       pkey->last_written = ss_time();
04759 
04760       db_notify_clients(hDB, hKey, TRUE);
04761       db_unlock_database(hDB);
04762 
04763    }
04764 #endif                          /* LOCAL_ROUTINES */
04765 
04766    return DB_SUCCESS;
04767 }

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

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:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Handle for key where search starts, zero for root.
data Pointer to single value of data.
data_size 
idx Size of single data element.
type Type 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 5006 of file odb.c.

Referenced by add_event(), cm_register_transition(), command_loop(), db_paste_node(), db_set_data(), db_set_value_index(), interprete(), load_parameters(), resize_vars_odb(), rpc_server_dispatch(), save_vars_odb(), show_create_page(), show_custom_page(), show_odb_tag(), and show_sc_page().

05007 {
05008    if (rpc_is_remote())
05009       return rpc_call(RPC_DB_SET_DATA_INDEX, hDB, hKey, data, data_size, idx, type);
05010 
05011 #ifdef LOCAL_ROUTINES
05012    {
05013       DATABASE_HEADER *pheader;
05014       KEY *pkey;
05015       char link_name[256], str[256];
05016       int link_idx;
05017       HNDLE hkeylink;
05018 
05019       if (hDB > _database_entries || hDB <= 0) {
05020          cm_msg(MERROR, "db_set_data_index", "invalid database handle");
05021          return DB_INVALID_HANDLE;
05022       }
05023 
05024       if (!_database[hDB - 1].attached) {
05025          cm_msg(MERROR, "db_set_data_index", "invalid database handle");
05026          return DB_INVALID_HANDLE;
05027       }
05028 
05029       if (hKey < (int) sizeof(DATABASE_HEADER)) {
05030          cm_msg(MERROR, "db_set_data_index", "invalid key handle");
05031          return DB_INVALID_HANDLE;
05032       }
05033 
05034       db_lock_database(hDB);
05035 
05036       pheader = _database[hDB - 1].database_header;
05037       pkey = (KEY *) ((char *) pheader + hKey);
05038 
05039       /* check if hKey argument is correct */
05040       if (!db_validate_hkey(pheader, hKey)) {
05041          db_unlock_database(hDB);
05042          return DB_INVALID_HANDLE;
05043       }
05044 
05045       /* check for write access */
05046       if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
05047          db_unlock_database(hDB);
05048          return DB_NO_ACCESS;
05049       }
05050 
05051       /* check for link to array index */
05052       if (pkey->type == TID_LINK) {
05053          strlcpy(link_name, (char *) pheader + pkey->data, sizeof(link_name));
05054          if (strlen(link_name) > 0 && link_name[strlen(link_name) - 1] == ']') {
05055             db_unlock_database(hDB);
05056             if (strchr(link_name, '[') == NULL)
05057                return DB_INVALID_LINK;
05058             link_idx = atoi(strchr(link_name, '[') + 1);
05059             *strchr(link_name, '[') = 0;
05060             if (db_find_key(hDB, 0, link_name, &hkeylink) != DB_SUCCESS)
05061                return DB_INVALID_LINK;
05062             return db_set_data_index(hDB, hkeylink, data, data_size, link_idx, type);
05063          }
05064       }
05065 
05066       if (pkey->type != type) {
05067          db_unlock_database(hDB);
05068          db_get_path(hDB, hKey, str, sizeof(str));
05069          cm_msg(MERROR, "db_set_data_index",
05070                 "\"%s\" is of type %s, not %s", str, rpc_tid_name(pkey->type), rpc_tid_name(type));
05071          return DB_TYPE_MISMATCH;
05072       }
05073 
05074       /* keys cannot contain data */
05075       if (pkey->type == TID_KEY) {
05076          db_unlock_database(hDB);
05077          cm_msg(MERROR, "db_set_data_index", "key cannot contain data");
05078          return DB_TYPE_MISMATCH;
05079       }
05080 
05081       /* check for valid idx */
05082       if (idx < 0) {
05083          db_unlock_database(hDB);
05084          cm_msg(MERROR, "db_set_data_index", "invalid index %d", idx);
05085          return DB_FULL;
05086       }
05087 
05088       /* check for valid array element size: if new element size
05089          is different from existing size, ODB becomes corrupted */
05090       if (pkey->item_size != 0 && data_size != pkey->item_size) {
05091          db_unlock_database(hDB);
05092          cm_msg(MERROR, "db_set_data_index", "invalid element data size %d, expected %d", data_size, pkey->item_size);
05093          return DB_TYPE_MISMATCH;
05094       }
05095 
05096       /* increase data size if necessary */
05097       if (idx >= pkey->num_values || pkey->item_size == 0) {
05098          pkey->data =
05099              (POINTER_T) realloc_data(pheader, (char *) pheader + pkey->data, pkey->total_size, data_size * (idx + 1));
05100 
05101          if (pkey->data == 0) {
05102             db_unlock_database(hDB);
05103             cm_msg(MERROR, "db_set_data_index", "online database full");
05104             return DB_FULL;
05105          }
05106 
05107          pkey->data -= (POINTER_T) pheader;
05108          if (!pkey->item_size)
05109             pkey->item_size = data_size;
05110          pkey->total_size = data_size * (idx + 1);
05111          pkey->num_values = idx + 1;
05112       }
05113 
05114       /* cut strings which are too long */
05115       if ((type == TID_STRING || type == TID_LINK) && (int) strlen((char *) data) + 1 > pkey->item_size)
05116          *((char *) data + pkey->item_size - 1) = 0;
05117 
05118       /* copy data */
05119       memcpy((char *) pheader + pkey->data + idx * pkey->item_size, data, pkey->item_size);
05120 
05121       /* update time */
05122       pkey->last_written = ss_time();
05123 
05124       db_notify_clients(hDB, hKey, TRUE);
05125       db_unlock_database(hDB);
05126 
05127    }
05128 #endif                          /* LOCAL_ROUTINES */
05129 
05130    return DB_SUCCESS;
05131 }

INT 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:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Handle for key where search starts, zero for root.
data Buffer from which data gets copied to.
buf_size Size of data buffer.
num_values Number of data values (for arrays).
type Type of key, one of TID_xxx (see Midas Data Types).
Returns:
DB_SUCCESS, DB_INVALID_HANDLE, DB_TRUNCATED

Definition at line 4780 of file odb.c.

Referenced by command_loop(), db_paste(), rpc_server_dispatch(), and show_set_page().

04781 {
04782    if (rpc_is_remote())
04783       return rpc_call(RPC_DB_SET_LINK_DATA, hDB, hKey, data, buf_size, num_values, type);
04784 
04785 #ifdef LOCAL_ROUTINES
04786    {
04787       DATABASE_HEADER *pheader;
04788       KEY *pkey;
04789 
04790       if (hDB > _database_entries || hDB <= 0) {
04791          cm_msg(MERROR, "db_set_data", "invalid database handle");
04792          return DB_INVALID_HANDLE;
04793       }
04794 
04795       if (!_database[hDB - 1].attached) {
04796          cm_msg(MERROR, "db_set_data", "invalid database handle");
04797          return DB_INVALID_HANDLE;
04798       }
04799 
04800       if (hKey < (int) sizeof(DATABASE_HEADER)) {
04801          cm_msg(MERROR, "db_set_data", "invalid key handle");
04802          return DB_INVALID_HANDLE;
04803       }
04804 
04805       if (num_values == 0)
04806          return DB_INVALID_PARAM;
04807 
04808       db_lock_database(hDB);
04809 
04810       pheader = _database[hDB - 1].database_header;
04811       pkey = (KEY *) ((char *) pheader + hKey);
04812 
04813       /* check if hKey argument is correct */
04814       if (!db_validate_hkey(pheader, hKey)) {
04815          db_unlock_database(hDB);
04816          return DB_INVALID_HANDLE;
04817       }
04818 
04819       /* check for write access */
04820       if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
04821          db_unlock_database(hDB);
04822          return DB_NO_ACCESS;
04823       }
04824 
04825       if (pkey->type != type) {
04826          db_unlock_database(hDB);
04827          cm_msg(MERROR, "db_set_link_data", "\"%s\" is of type %s, not %s",
04828                 pkey->name, rpc_tid_name(pkey->type), rpc_tid_name(type));
04829          return DB_TYPE_MISMATCH;
04830       }
04831 
04832       /* keys cannot contain data */
04833       if (pkey->type == TID_KEY) {
04834          db_unlock_database(hDB);
04835          cm_msg(MERROR, "db_set_link_data", "Key cannot contain data");
04836          return DB_TYPE_MISMATCH;
04837       }
04838 
04839       /* if no buf_size given (Java!), calculate it */
04840       if (buf_size == 0)
04841          buf_size = pkey->item_size * num_values;
04842 
04843       /* resize data size if necessary */
04844       if (pkey->total_size != buf_size) {
04845          pkey->data = (POINTER_T) realloc_data(pheader, (char *) pheader + pkey->data, pkey->total_size, buf_size);
04846 
04847          if (pkey->data == 0) {
04848             db_unlock_database(hDB);
04849             cm_msg(MERROR, "db_set_link_data", "online database full");
04850             return DB_FULL;
04851          }
04852 
04853          pkey->data -= (POINTER_T) pheader;
04854          pkey->total_size = buf_size;
04855       }
04856 
04857       /* set number of values */
04858       pkey->num_values = num_values;
04859       if (num_values)
04860          pkey->item_size = buf_size / num_values;
04861 
04862       /* copy data */
04863       memcpy((char *) pheader + pkey->data, data, buf_size);
04864 
04865       /* update time */
04866       pkey->last_written = ss_time();
04867 
04868       db_notify_clients(hDB, hKey, TRUE);
04869       db_unlock_database(hDB);
04870 
04871    }
04872 #endif                          /* LOCAL_ROUTINES */
04873 
04874    return DB_SUCCESS;
04875 }

INT 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:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Handle for key where search starts, zero for root.
data Pointer to single value of data.
data_size 
idx Size of single data element.
type Type 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 5145 of file odb.c.

Referenced by command_loop(), rpc_server_dispatch(), set_key(), and show_set_page().

05146 {
05147    if (rpc_is_remote())
05148       return rpc_call(RPC_DB_SET_LINK_DATA_INDEX, hDB, hKey, data, data_size, idx, type);
05149 
05150 #ifdef LOCAL_ROUTINES
05151    {
05152       DATABASE_HEADER *pheader;
05153       KEY *pkey;
05154       char str[256];
05155 
05156       if (hDB > _database_entries || hDB <= 0) {
05157          cm_msg(MERROR, "db_set_data_index", "invalid database handle");
05158          return DB_INVALID_HANDLE;
05159       }
05160 
05161       if (!_database[hDB - 1].attached) {
05162          cm_msg(MERROR, "db_set_data_index", "invalid database handle");
05163          return DB_INVALID_HANDLE;
05164       }
05165 
05166       if (hKey < (int) sizeof(DATABASE_HEADER)) {
05167          cm_msg(MERROR, "db_set_data_index", "invalid key handle");
05168          return DB_INVALID_HANDLE;
05169       }
05170 
05171       db_lock_database(hDB);
05172 
05173       pheader = _database[hDB - 1].database_header;
05174       pkey = (KEY *) ((char *) pheader + hKey);
05175 
05176       /* check if hKey argument is correct */
05177       if (!db_validate_hkey(pheader, hKey)) {
05178          db_unlock_database(hDB);
05179          return DB_INVALID_HANDLE;
05180       }
05181 
05182       /* check for write access */
05183       if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
05184          db_unlock_database(hDB);
05185          return DB_NO_ACCESS;
05186       }
05187 
05188       if (pkey->type != type) {
05189          db_unlock_database(hDB);
05190          db_get_path(hDB, hKey, str, sizeof(str));
05191          cm_msg(MERROR, "db_set_data_index",
05192                 "\"%s\" is of type %s, not %s", str, rpc_tid_name(pkey->type), rpc_tid_name(type));
05193          return DB_TYPE_MISMATCH;
05194       }
05195 
05196       /* keys cannot contain data */
05197       if (pkey->type == TID_KEY) {
05198          db_unlock_database(hDB);
05199          cm_msg(MERROR, "db_set_data_index", "key cannot contain data");
05200          return DB_TYPE_MISMATCH;
05201       }
05202 
05203       /* check for valid array element size: if new element size
05204          is different from existing size, ODB becomes corrupted */
05205       if (pkey->item_size != 0 && data_size != pkey->item_size) {
05206          db_unlock_database(hDB);
05207          cm_msg(MERROR, "db_set_data_index", "invalid element data size %d, expected %d", data_size, pkey->item_size);
05208          return DB_TYPE_MISMATCH;
05209       }
05210 
05211       /* increase data size if necessary */
05212       if (idx >= pkey->num_values || pkey->item_size == 0) {
05213          pkey->data =
05214              (POINTER_T) realloc_data(pheader, (char *) pheader + pkey->data, pkey->total_size, data_size * (idx + 1));
05215 
05216          if (pkey->data == 0) {
05217             db_unlock_database(hDB);
05218             cm_msg(MERROR, "db_set_data_index", "online database full");
05219             return DB_FULL;
05220          }
05221 
05222          pkey->data -= (POINTER_T) pheader;
05223          if (!pkey->item_size)
05224             pkey->item_size = data_size;
05225          pkey->total_size = data_size * (idx + 1);
05226          pkey->num_values = idx + 1;
05227       }
05228 
05229       /* cut strings which are too long */
05230       if ((type == TID_STRING || type == TID_LINK) && (int) strlen((char *) data) + 1 > pkey->item_size)
05231          *((char *) data + pkey->item_size - 1) = 0;
05232 
05233       /* copy data */
05234       memcpy((char *) pheader + pkey->data + idx * pkey->item_size, data, pkey->item_size);
05235 
05236       /* update time */
05237       pkey->last_written = ss_time();
05238 
05239       db_notify_clients(hDB, hKey, TRUE);
05240       db_unlock_database(hDB);
05241 
05242    }
05243 #endif                          /* LOCAL_ROUTINES */
05244 
05245    return DB_SUCCESS;
05246 }

INT 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)
    status = db_set_record(hDB, hKeyst, &lazyst, size, 0);
  else
    cm_msg(MERROR,"task","record %s/statistics not found", pLch->name)
...
Parameters:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Handle for key where search starts, zero for root.
data Pointer where data is stored.
buf_size Size of data structure, must be obtained via sizeof(RECORD-NAME).
align Byte 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 7587 of file odb.c.

Referenced by al_check(), al_reset_alarm(), al_trigger_alarm(), close_channels(), db_open_record(), db_send_changed_records(), lazy_main(), main(), register_equipment(), register_requests(), rpc_server_dispatch(), tr_start(), tr_stop(), update_odb(), and write_event_odb().

07588 {
07589    if (rpc_is_remote()) {
07590       align = ss_get_struct_align();
07591       return rpc_call(RPC_DB_SET_RECORD, hDB, hKey, data, buf_size, align);
07592    }
07593 #ifdef LOCAL_ROUTINES
07594    {
07595       KEY key;
07596       INT convert_flags;
07597       INT total_size;
07598       void *pdata;
07599 
07600       convert_flags = 0;
07601 
07602       if (!align)
07603          align = ss_get_struct_align();
07604       else
07605          /* only convert data if called remotely, as indicated by align != 0 */
07606       if (rpc_get_server_option(RPC_OSERVER_TYPE) != ST_REMOTE)
07607          convert_flags = rpc_get_server_option(RPC_CONVERT_FLAGS);
07608 
07609       /* check if key has subkeys */
07610       db_get_key(hDB, hKey, &key);
07611       if (key.type != TID_KEY) {
07612          /* copy single key */
07613          if (key.item_size * key.num_values != buf_size) {
07614             cm_msg(MERROR, "db_set_record", "struct size mismatch for \"%s\"", key.name);
07615             return DB_STRUCT_SIZE_MISMATCH;
07616          }
07617 
07618          if (convert_flags) {
07619             if (key.num_values > 1)
07620                rpc_convert_data(data, key.type, RPC_FIXARRAY, key.item_size * key.num_values, convert_flags);
07621             else
07622                rpc_convert_single(data, key.type, 0, convert_flags);
07623          }
07624 
07625          db_set_data(hDB, hKey, data, key.total_size, key.num_values, key.type);
07626          return DB_SUCCESS;
07627       }
07628 
07629       /* check record size */
07630       db_get_record_size(hDB, hKey, 0, &total_size);
07631       if (total_size != buf_size) {
07632          cm_msg(MERROR, "db_set_record", "struct size mismatch for \"%s\"", key.name);
07633          return DB_STRUCT_SIZE_MISMATCH;
07634       }
07635 
07636       /* set subkey data */
07637       pdata = data;
07638       total_size = 0;
07639 
07640       db_lock_database(hDB);
07641       db_recurse_record_tree(hDB, hKey, &pdata, &total_size, align, NULL, TRUE, convert_flags);
07642       db_notify_clients(hDB, hKey, TRUE);
07643       db_unlock_database(hDB);
07644    }
07645 #endif                          /* LOCAL_ROUTINES */
07646 
07647    return DB_SUCCESS;
07648 }

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

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_INT);
Parameters:
hDB ODB handle obtained via cm_get_experiment_database().
hKeyRoot Handle for key where search starts, zero for root.
key_name Name of key to search, can contain directories.
data Address of data.
data_size Size of data (in bytes).
num_values Number of data elements.
type Type 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 3005 of file odb.c.

Referenced by add_event(), al_trigger_alarm(), analyze_run(), cm_connect_experiment1(), cm_delete_client_info(), cm_register_deferred_transition(), cm_register_transition(), cm_set_client_info(), cm_set_transition_sequence(), cm_set_watchdog_params(), cm_transition1(), command_loop(), db_create_link(), db_get_value(), get_event_id(), lazy_main(), lazy_maintain_check(), log_callback(), log_generate_file_name(), log_write(), main(), mana_init(), process_event(), register_equipment(), rpc_server_dispatch(), set_equipment_status(), show_alarm_page(), show_elog_new(), show_elog_query(), show_hist_config_page(), show_hist_page(), test_write(), tr_start(), and update_odb().

03007 {
03008    if (rpc_is_remote())
03009       return rpc_call(RPC_DB_SET_VALUE, hDB, hKeyRoot, key_name, data, data_size, num_values, type);
03010 
03011 #ifdef LOCAL_ROUTINES
03012    {
03013       DATABASE_HEADER *pheader;
03014       KEY *pkey;
03015       HNDLE hKey;
03016       INT status;
03017 
03018       if (num_values == 0)
03019          return DB_INVALID_PARAM;
03020 
03021       status = db_find_key(hDB, hKeyRoot, key_name, &hKey);
03022       if (status == DB_NO_KEY) {
03023          db_create_key(hDB, hKeyRoot, key_name, type);
03024          status = db_find_link(hDB, hKeyRoot, key_name, &hKey);
03025       }
03026 
03027       if (status != DB_SUCCESS)
03028          return status;
03029 
03030       db_lock_database(hDB);
03031       pheader = _database[hDB - 1].database_header;
03032 
03033       /* get address from handle */
03034       pkey = (KEY *) ((char *) pheader + hKey);
03035 
03036       /* check for write access */
03037       if (!(pkey->access_mode & MODE_WRITE) || (pkey->access_mode & MODE_EXCLUSIVE)) {
03038          db_unlock_database(hDB);
03039          return DB_NO_ACCESS;
03040       }
03041 
03042       if (pkey->type != type) {
03043          db_unlock_database(hDB);
03044          cm_msg(MERROR, "db_set_value", "\"%s\" is of type %s, not %s",
03045                 key_name, rpc_tid_name(pkey->type), rpc_tid_name(type));
03046          return DB_TYPE_MISMATCH;
03047       }
03048 
03049       /* keys cannot contain data */
03050       if (pkey->type == TID_KEY) {
03051          db_unlock_database(hDB);
03052          cm_msg(MERROR, "db_set_value", "key cannot contain data");
03053          return DB_TYPE_MISMATCH;
03054       }
03055 
03056       if (data_size == 0) {
03057          db_unlock_database(hDB);
03058          cm_msg(MERROR, "db_set_value", "zero data size not allowed");
03059          return DB_TYPE_MISMATCH;
03060       }
03061 
03062       if (type != TID_STRING && type != TID_LINK && data_size != rpc_tid_size(type) * num_values) {
03063          db_unlock_database(hDB);
03064          cm_msg(MERROR, "db_set_value", "data_size (%d) does not match num_values (%d)", data_size, num_values);
03065          return DB_TYPE_MISMATCH;
03066       }
03067 
03068       /* resize data size if necessary */
03069       if (pkey->total_size != data_size) {
03070          pkey->data = (POINTER_T) realloc_data(pheader, (char *) pheader + pkey->data, pkey->total_size, data_size);
03071 
03072          if (pkey->data == 0) {
03073             db_unlock_database(hDB);
03074             cm_msg(MERROR, "db_set_value", "online database full");
03075             return DB_FULL;
03076          }
03077 
03078          pkey->data -= (POINTER_T) pheader;
03079          pkey->total_size = data_size;
03080       }
03081 
03082       /* set number of values */
03083       pkey->num_values = num_values;
03084 
03085       if (type == TID_STRING || type == TID_LINK)
03086          pkey->item_size = data_size / num_values;
03087       else
03088          pkey->item_size = rpc_tid_size(type);
03089 
03090       /* copy data */
03091       memcpy((char *) pheader + pkey->data, data, data_size);
03092 
03093       /* update time */
03094       pkey->last_written = ss_time();
03095 
03096       db_notify_clients(hDB, hKey, TRUE);
03097       db_unlock_database(hDB);
03098 
03099    }
03100 #endif                          /* LOCAL_ROUTINES */
03101 
03102    return DB_SUCCESS;
03103 }

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 
)

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_INT, FALSE);
Parameters:
hDB ODB handle obtained via cm_get_experiment_database().
hKeyRoot Handle for key where search starts, zero for root.
key_name Name of key to search, can contain directories.
data Address of data.
data_size Size of data (in bytes).
index Array index of value.
type Type of key, one of TID_xxx (see Midas Data Types)
truncate Truncate array to current index if TRUE
Returns:
<same as db_set_data_index>

Definition at line 3129 of file odb.c.

03131 {
03132    HNDLE hkey;
03133 
03134    db_find_key(hDB, hKeyRoot, key_name, &hkey);
03135    if (!hkey) {
03136       db_create_key(hDB, hKeyRoot, key_name, type);
03137       db_find_key(hDB, hKeyRoot, key_name, &hkey);
03138       assert(hkey);
03139    }
03140    if (trunc)
03141       db_set_num_values(hDB, hkey, idx + 1);
03142 
03143    return db_set_data_index(hDB, hkey, data, data_size, idx, type);
03144 }

INT db_sprintf ( char *  string,
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++)
  {
    db_sprintf(pbuf, pdata, key.item_size, j, key.type);
    strcat(pbuf, "\n");
  }
  ...
Parameters:
string output ASCII string of data.
data Value data.
data_size Size of single data element.
idx Index for array data.
type Type of key, one of TID_xxx (see Midas Data Types).
Returns:
DB_SUCCESS

Definition at line 6945 of file odb.c.

Referenced by ascii_write(), cmd_dir(), command_loop(), condition_test(), db_copy(), db_save_xml_key(), dump_write(), evaluate_src(), exec_script(), gen_odb_attachment(), hs_dump(), print_key(), scan_tree(), search_callback(), search_key(), show_custom_gif(), show_custom_page(), show_odb_page(), show_odb_tag(), show_sc_page(), show_set_page(), show_start_page(), and write_event_ascii().

06946 {
06947    if (data_size == 0)
06948       sprintf(string, "<NULL>");
06949    else
06950       switch (type) {
06951       case TID_BYTE:
06952          sprintf(string, "%d", *(((BYTE *) data) + idx));
06953          break;
06954       case TID_SBYTE:
06955          sprintf(string, "%d", *(((char *) data) + idx));
06956          break;
06957       case TID_CHAR:
06958          sprintf(string, "%c", *(((char *) data) + idx));
06959          break;
06960       case TID_WORD:
06961          sprintf(string, "%u", *(((WORD *) data) + idx));
06962          break;
06963       case TID_SHORT:
06964          sprintf(string, "%d", *(((short *) data) + idx));
06965          break;
06966       case TID_DWORD:
06967          sprintf(string, "%u", *(((DWORD *) data) + idx));
06968          break;
06969       case TID_INT:
06970          sprintf(string, "%d", *(((INT *) data) + idx));
06971          break;
06972       case TID_BOOL:
06973          sprintf(string, "%c", *(((BOOL *) data) + idx) ? 'y' : 'n');
06974          break;
06975       case TID_FLOAT:
06976          if (ss_isnan(*(((float *) data) + idx)))
06977             sprintf(string, "NAN");
06978          else
06979             sprintf(string, "%.7g", *(((float *) data) + idx));
06980          break;
06981       case TID_DOUBLE:
06982          if (ss_isnan(*(((double *) data) + idx)))
06983             sprintf(string, "NAN");
06984          else
06985             sprintf(string, "%.16lg", *(((double *) data) + idx));
06986          break;
06987       case TID_BITFIELD:
06988          /* TBD */
06989          break;
06990       case TID_STRING:
06991       case TID_LINK:
06992          strlcpy(string, ((char *) data) + data_size * idx, MAX_STRING_LENGTH);
06993          break;
06994       default:
06995          sprintf(string, "<unknown>");
06996          break;
06997       }
06998 
06999    return DB_SUCCESS;
07000 }

INT 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:
string output ASCII string of data.
format Format specifier passed to sprintf()
data Value data.
data_size Size of single data element.
idx Index for array data.
type Type of key, one of TID_xxx (see Midas Data Types).
Returns:
DB_SUCCESS

Definition at line 7015 of file odb.c.

Referenced by show_custom_page(), and show_odb_tag().

07016 {
07017    if (data_size == 0)
07018       sprintf(string, "<NULL>");
07019    else
07020       switch (type) {
07021       case TID_BYTE:
07022          sprintf(string, format, *(((BYTE *) data) + idx));
07023          break;
07024       case TID_SBYTE:
07025          sprintf(string, format, *(((char *) data) + idx));
07026          break;
07027       case TID_CHAR:
07028          sprintf(string, format, *(((char *) data) + idx));
07029          break;
07030       case TID_WORD:
07031          sprintf(string, format, *(((WORD *) data) + idx));
07032          break;
07033       case TID_SHORT:
07034          sprintf(string, format, *(((short *) data) + idx));
07035          break;
07036       case TID_DWORD:
07037          sprintf(string, format, *(((DWORD *) data) + idx));
07038          break;
07039       case TID_INT:
07040          sprintf(string, format, *(((INT *) data) + idx));
07041          break;
07042       case TID_BOOL:
07043          sprintf(string, format, *(((BOOL *) data) + idx) ? 'y' : 'n');
07044          break;
07045       case TID_FLOAT:
07046          if (ss_isnan(*(((float *) data) + idx)))
07047             sprintf(string, "NAN");
07048          else
07049             sprintf(string, format, *(((float *) data) + idx));
07050          break;
07051       case TID_DOUBLE:
07052          if (ss_isnan(*(((double *) data) + idx)))
07053             sprintf(string, "NAN");
07054          else
07055             sprintf(string, format, *(((double *) data) + idx));
07056          break;
07057       case TID_BITFIELD:
07058          /* TBD */
07059          break;
07060       case TID_STRING:
07061       case TID_LINK:
07062          strlcpy(string, ((char *) data) + data_size * idx, MAX_STRING_LENGTH);
07063          break;
07064       default:
07065          sprintf(string, "<unknown>");
07066          break;
07067       }
07068 
07069    return DB_SUCCESS;
07070 }

INT db_unlock_database ( HNDLE  hDB  ) 

Unlock a database via system semaphore calls.

Parameters:
hDB Handle to the database to unlock
Returns:
DB_SUCCESS, DB_INVALID_HANDLE

Definition at line 1456 of file odb.c.

Referenced by cm_check_client(), cm_delete_client_info(), cm_get_watchdog_info(), cm_set_client_info(), cm_set_watchdog_params(), db_close_database(), db_create_key(), db_create_record(), db_delete_key1(), db_enum_key(), db_find_key(), db_get_data(), db_get_data_index(), db_get_key(), db_get_key_info(), db_get_key_time(), db_get_link(), db_get_link_data(), db_get_record(), db_get_record_size(), db_get_value(), db_open_database(), db_set_data(), db_set_data_index(), db_set_link_data(), db_set_link_data_index(), db_set_record(), db_set_value(), and log_system_history().

01457 {
01458 
01459 #ifdef LOCAL_ROUTINES
01460 
01461 #ifdef CHECK_THREAD_ID
01462    if (_lock_tid == 0)
01463       _lock_tid = ss_gettid();
01464 
01465    assert(_lock_tid == ss_gettid());
01466 #endif
01467 
01468    if (hDB > _database_entries || hDB <= 0) {
01469       cm_msg(MERROR, "db_unlock_database", "invalid database handle");
01470       return DB_INVALID_HANDLE;
01471    }
01472 #ifdef CHECK_LOCK_COUNT
01473    {
01474       char str[256];
01475 
01476       sprintf(str, "db_unlock_database, lock_cnt=%d", _database[hDB - 1].lock_cnt);
01477       ss_stack_history_entry(str);
01478    }
01479 #endif
01480 
01481    if (_database[hDB - 1].lock_cnt == 1)
01482       ss_semaphore_release(_database[hDB - 1].semaphore);
01483 
01484    if (_database[hDB - 1].lock_cnt > 0)
01485       _database[hDB - 1].lock_cnt--;
01486 
01487    if (_database[hDB - 1].protect) {
01488       ss_shm_protect(_database[hDB - 1].shm_handle, _database[hDB - 1].database_header);
01489       _database[hDB - 1].database_header = NULL;
01490    }
01491 #endif                          /* LOCAL_ROUTINES */
01492    return DB_SUCCESS;
01493 }

INT db_update_record ( INT  hDB,
INT  hKey,
int  s 
)

If called locally, update a record (hDB/hKey) and copy its new contents to the local copy of it.

If called from a server, send a network notification to the client.

Parameters:
hDB ODB handle obtained via cm_get_experiment_database().
hKey Handle for key where search starts, zero for root.
s optional server socket
Returns:
DB_SUCCESS, DB_INVALID_HANDLE

Definition at line 8664 of file odb.c.

08665 {
08666    INT i, size, convert_flags, status;
08667    char buffer[32];
08668    NET_COMMAND *nc;
08669 
08670    /* check if we are the server */
08671    if (s) {
08672       convert_flags = rpc_get_server_option(RPC_CONVERT_FLAGS);
08673 
08674       if (convert_flags & CF_ASCII) {
08675          sprintf(buffer, "MSG_ODB&%d&%d", hDB, hKey);
08676          send_tcp(s, buffer, strlen(buffer) + 1, 0);
08677       } else {
08678          nc = (NET_COMMAND *) buffer;
08679 
08680          nc->header.routine_id = MSG_ODB;
08681          nc->header.param_size = 2 * sizeof(INT);
08682          *((INT *) nc->param) = hDB;
08683          *((INT *) nc->param + 1) = hKey;
08684 
08685          if (convert_flags) {
08686             rpc_convert_single(&nc->header.routine_id, TID_DWORD, RPC_OUTGOING, convert_flags);
08687             rpc_convert_single(&nc->header.param_size, TID_DWORD, RPC_OUTGOING, convert_flags);
08688             rpc_convert_single(&nc->param[0], TID_DWORD, RPC_OUTGOING, convert_flags);
08689             rpc_convert_single(&nc->param[4], TID_DWORD, RPC_OUTGOING, convert_flags);
08690          }
08691 
08692          /* send the update notification to the client */
08693          send_tcp(s, buffer, sizeof(NET_COMMAND_HEADER) + 2 * sizeof(INT), 0);
08694       }
08695 
08696       return DB_SUCCESS;
08697    }
08698 
08699    status = DB_INVALID_HANDLE;
08700 
08701    /* check all entries for matching key */
08702    for (i = 0; i < _record_list_entries; i++)
08703       if (_record_list[i].handle == hKey) {
08704          status = DB_SUCCESS;
08705 
08706          /* get updated data if record not opened in write mode */
08707          if ((_record_list[i].access_mode & MODE_WRITE) == 0) {
08708             size = _record_list[i].buf_size;
08709             if (_record_list[i].data != NULL)
08710                db_get_record(hDB, hKey, _record_list[i].data, &size, 0);
08711 
08712             /* call dispatcher if requested */
08713             if (_record_list[i].dispatcher)
08714                _record_list[i].dispatcher(hDB, hKey, _record_list[i].info);
08715          }
08716       }
08717 
08718    return DB_SUCCESS;
08719 }

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

Definition at line 1554 of file odb.c.

Referenced by add_event(), al_check(), bm_open_buffer(), bor(), cm_connect_client(), cm_connect_experiment1(), cm_exist(), cm_get_watchdog_info(), cm_list_experiments(), cm_set_client_info(), cm_shutdown(), cmd_dir(), command_loop(), create_experim_h(), db_check_record(), db_create_key(), db_find_key(), db_get_event_definition(), db_open_database(), db_paste(), db_paste_node(), decode_get(), evaluate_src(), export_hist(), find_odb_tag(), FindIndexByColumnName(), FindIndexByEventName(), FindIndexByTableName(), FindIndexByTagName(), gen_odb_attachment(), generate_hist_graph(), get_event_id(), get_variable_id(), get_variable_id_tags(), MidasHistory::GetEventsFromOdbEvents(), MidasHistory::GetEventsFromOdbTags(), getparam(), MidasHistory::GetTagsFromOdb(), SqlHistory::hs_read_old_style(), interprete(), is_editable(), isparam(), lazy_condition_check(), lazy_copy(), lazy_log_update(), lazy_main(), log_callback(), log_open(), logger_root(), main(), print_help(), register_equipment(), send_icon(), set_equipment_status(), setparam(), show_cnaf_page(), show_custom_gif(), show_custom_page(), show_elog_new(), show_elog_page(), show_elog_submit_query(), show_form_query(), show_header(), show_hist_config_page(), show_hist_page(), show_odb_page(), show_odb_tag(), show_programs_page(), show_query_page(), show_rawfile(), show_sc_page(), show_set_page(), show_start_page(), show_status_page(), submit_form(), tr_start(), unsetparam(), and MidasHistory::xhs_event_id().

01555 {
01556    if (str1 == NULL && str2 != NULL)
01557       return FALSE;
01558    if (str1 != NULL && str2 == NULL)
01559       return FALSE;
01560    if (str1 == NULL && str2 == NULL)
01561       return TRUE;
01562    if (strlen(str1) != strlen(str2))
01563       return FALSE;
01564 
01565    while (*str1)
01566       if (toupper(*str1++) != toupper(*str2++))
01567          return FALSE;
01568 
01569    if (*str2)
01570       return FALSE;
01571 
01572    return TRUE;
01573 }

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

Definition at line 1540 of file odb.c.

Referenced by db_create_key(), and db_find_key().

01541 {
01542    int i = 0;
01543 
01544    if (*key_list == '/')
01545       key_list++;
01546 
01547    while (*key_list && *key_list != '/' && ++i < key_name_length)
01548       *key_name++ = *key_list++;
01549    *key_name = 0;
01550 
01551    return key_list;
01552 }

void xml_encode ( char *  src,
int  size 
)

Definition at line 6573 of file odb.c.

06574 {
06575    int i;
06576    char *dst, *p;
06577 
06578    dst = (char *) malloc(size);
06579    if (dst == NULL)
06580       return;
06581 
06582    *dst = 0;
06583    for (i = 0; i < (int) strlen(src); i++) {
06584       switch (src[i]) {
06585       case '<':
06586          strlcat(dst, "&lt;", size);
06587          break;
06588       case '>':
06589          strlcat(dst, "&gt;", size);
06590          break;
06591       case '&':
06592          strlcat(dst, "&amp;", size);
06593          break;
06594       case '\"':
06595          strlcat(dst, "&quot;", size);
06596          break;
06597       case '\'':
06598          strlcat(dst, "&apos;", size);
06599          break;
06600       default:
06601          if ((int) strlen(dst) >= size) {
06602             free(dst);
06603             return;
06604          }
06605          p = dst + strlen(dst);
06606          *p = src[i];
06607          *(p + 1) = 0;
06608       }
06609    }
06610 
06611    strlcpy(src, dst, size);
06612 }


Midas DOC Version 3.0.0 ---- PSI Stefan Ritt ----
Contributions: Pierre-Andre Amaudruz - Sergio Ballestrero - Suzannah Daviel - Doxygen - Peter Green - Qing Gu - Greg Hackman - Gertjan Hofman - Paul Knowles - Exaos Lee - Rudi Meier - Glenn Moloney - Dave Morris - John M O'Donnell - Konstantin Olchanski - Renee Poutissou - Tamsen Schurman - Andreas Suter - Jan M.Wouters - Piotr Adam Zolnierczuk