sim_db for C

Minimal Example using C

A parameter file called params_mininal_c_example.txt is located in the sim_db/examples/ directory in the source code. The file contains the following:

name (string): minimal_c_example

{cmake_config} (alias): cmake -Hroot/ -Broot/examples/build
{cmake_build} (alias): {cmake_config}; cmake --build root/examples/build --target

run_command (string): {cmake_build} minimal_c_example; root/examples/build/minimal_c_example

param1 (string): "Minimal C example is running."

param2 (int): 42

A C file called minimal_example.c and is found in the same directory:

#include "sim_db.h"  // Parts from the standard library is also included.

int main(int argc, char** argv) {
    // Open database and write some initial metadata to database.
    SimDB* sim_db = sim_db_ctor(argc, argv);

    // Read parameters from database.
    char* param1 = sim_db_read_string(sim_db, "param1");
    int param2 = sim_db_read_int(sim_db, "param2");

    // Demonstrate that the simulation is running.
    printf("%s\n", param1);

    // Write final metadata to database and free memory allocated by sim_db.
    sim_db_dtor(sim_db);
}

Add the those simulations parameters to the sim_db database and run the simulation from within the sim_db/examples directory with:

$ sim_db add_and_run -f params_minimal_c_example.txt

Notice that when it is run, it first call two cmake commands to compile the code if needed. What cmake does is equvalient to the following command called from sim_db/examples/ (given that the static C library are compiled and located in sim_db/build/):

$ cc -o build/minimal_c_example minimal_example.c -I../include -L../build -lsimdbc -lpthread -ldl -m

The example is not really a minimal one. If you already have compiled your program into a executable called program located in the current directory, the lines starting with {...} (alias): can be removed and the run_command can be replaced with simpy run_command (string): ./program.

Extensive Example using C

A parameter file called params_extensive_c_example.txt is found in the sim_db/examples/ directory in the source code. This parameter file contains all the possible types available in addition to some comments:

This is a comment, as any line without a colon is a comment.
# Adding a hashtag to the start of a comment line, make the comment easier to recognize.

# The name parameter is highly recommended to include.
name (string): extensive_c_example

# It is also recommended to include a description to further explain the intention of 
# the simulation.
description (string): Extensive C example to demonstrate most features in sim_db.

# Aliases for cmake commands for compiling the example. 
{cmake_config} (alias): cmake -Hroot/ -Broot/examples/build
{cmake_build} (alias): {cmake_config}; cmake --build root/examples/build --target

# This 'run_command' starts with an alias that is replaced with the above two cmake 
# commands that compile the extensitve example if needed. The last part of the 
# 'run_command' then run the compiled example. Each command is seperated by a 
# semicolon, but they all need to be on the same line.
run_command (string): {cmake_build} extensive_c_example; root/examples/build/extensive_c_example

# A parameter is added for each of the avaiable types.
param1_extensive (int): 3
param2_extensive (float): -0.5e10
param3_extensive (string): "Extensive C example is running."
param4_extensive (bool): True
param5_extensive (int array): [1, 2, 3]
param6_extensive (float array): [1.5, 2.5, 3.5]
param7_extensive (string array): ["a", "b", "c"]
param8_extensive (bool array): [True, False, True]

# Include parameters from another parameter file.
include_parameter_file: root/examples/extra_params_example.txt

# Change a parameter value from the included parameter file to demonstrate that
# it is the last parameter value that count for a given parameter name. 
extra_param1 (int): 9

The line in the parameter file starting with include_parameter_file: will be substituted with the contain of the specified extra_params_example.txt file, found in the same directory:

# Extra parameters included in the extensive examples.

extra_param1 (int): 7
extra_param2 (string): "Extra params added."
extra_param3 (bool): False

extensive_example.py is also found in the same directory:

#include "sim_db.h"  // Parts from the standard library is also included.

int main(int argc, char** argv) {
    // Open database and write some initial metadata to database.
    SimDB* sim_db = sim_db_ctor(argc, argv);

    // Read parameters from database.
    int param1 = sim_db_read_int(sim_db, "param1_extensive");
    double param2 = sim_db_read_double(sim_db, "param2_extensive");
    char* param3 = sim_db_read_string(sim_db, "param3_extensive");
    bool param4 = sim_db_read_bool(sim_db, "param4_extensive");
    SimDBIntVec param5 = sim_db_read_int_vec(sim_db, "param5_extensive");
    SimDBDoubleVec param6 = sim_db_read_double_vec(sim_db, "param6_extensive");
    SimDBStringVec param7 = sim_db_read_string_vec(sim_db, "param7_extensive");
    SimDBBoolVec param8 = sim_db_read_bool_vec(sim_db, "param8_extensive");

    // Show that SimDBIntVec contain array of integers and size.
    int* int_array = param5.array;
    int size_int_array = param5.size;

    // Demonstrate that the simulation is running.
    printf("%s\n", param3);

    // Write all the possible types to database.
    // Only these types are can be written to the database.
    sim_db_write_int(sim_db, "example_result_1", param1, false);
    sim_db_write_double(sim_db, "example_result_2", param2, true);
    sim_db_write_string(sim_db, "example_result_3", param3, false);
    sim_db_write_bool(sim_db, "example_result_4", param4, true);
    sim_db_write_int_array(sim_db, "example_result_5", param5.array,
                           param5.size, false);
    sim_db_write_double_array(sim_db, "example_result_6", param6.array,
                              param6.size, true);
    sim_db_write_string_array(sim_db, "example_result_7", param7.array,
                              param7.size, false);
    sim_db_write_bool_array(sim_db, "example_result_8", param8.array,
                            param8.size, true);

    // Make unique subdirectory for storing results and write its name to
    // database. Large results are recommended to be saved in this subdirectory.
    char* name_subdir =
            sim_db_unique_results_dir(sim_db, "root/examples/results");

    // Write some results to a file in the newly create subdirectory.
    FILE* result_file = fopen(strcat(name_subdir, "/results.txt"), "w");
    for (size_t i = 0; i < param6.size; i++) {
        fprintf(result_file, "%f\n", param6.array[i]);
    }
    fclose(result_file);

    // Check if column exists in database.
    bool is_column_in_database =
            sim_db_column_exists(sim_db, "column_not_in_database");

    // Check if column is empty and then set it to empty.
    bool is_empty = sim_db_is_empty(sim_db, "example_result_1");
    sim_db_set_empty(sim_db, "example_result_1");

    // Get the 'ID' of the connected simulation and the path to the project's
    // root directoy.
    int id = sim_db_get_id(sim_db);
    char path_proj_root[PATH_MAX + 1];
    strcpy(path_proj_root, sim_db_get_path_proj_root(sim_db));

    // Write final metadata to the database, close the connection and free
    // memory allocated by sim_db.
    sim_db_dtor(sim_db);

    // Add an empty simulation to the database, open connection and write to it.
    SimDB* sim_db_2 =
            sim_db_add_empty_sim_without_search(path_proj_root, false);
    sim_db_write_int(sim_db_2, "param1_extensive", 7, false);

    // Delete simulation from database.
    sim_db_delete_from_database(sim_db_2);

    // Close connection to the database and free memory allocated by sim_db.
    sim_db_dtor(sim_db_2);
}

Add the those simulations parameters to the sim_db database and run the simulation from within the sim_db/examples directory with:

$ sdb add_and_run -f params_extensive_c_example.txt

Notice that when it is run, it first call cmake to compile the code if needed. What cmake does is equvalient to the following command called from sim_db/examples/ (given that the static C library are compiled and located in sim_db/build/):

$ cc -o build/extensive_c_example extensive_example.c -I../include -L../build -lsimdbc -lpthread -ldl -m

C API Referance

Warning

doxygenfunction: Unable to resolve multiple matches for function “sim_db_ctor” with arguments (int, char**) in doxygen xml output for project “sim_db” from directory: /home/docs/checkouts/readthedocs.org/user_builds/sim-db/checkouts/latest/docs/xml/. Potential matches:

- SimDB *sim_db_ctor(int argc, char **argv)
- type(sim_db) function sim_db_mod::sim_db::sim_db_ctor (store_metadata)
- type(sim_db) function sim_db_mod::sim_db_ctor (store_metadata)
SimDB *sim_db_ctor_no_metadata(int argc, char **argv)

Initialize SimDB and connect to the sim_db database.

No metadata store automatically, and only explicit calls will write to the database. Should be used instead of sim_db_ctor() for postprocessing.

sim_db_dtor(SimDB*) MUST be called to clean up.

For multithreading/multiprocessing each thread/process MUST have its own connection.

Parameters
  • argc: Length of argv.

  • argv: Array of command line arguments containing --id 'ID' and optionally --path_proj_root 'PATH'. PATH is the root directory of the project, where *.sim_db/* is located. If not passed, the current working directory and its parent directories will be searched until *.sim_db/* is found.

Warning

doxygenfunction: Unable to resolve multiple matches for function “sim_db_ctor_with_id” with arguments (int, bool) in doxygen xml output for project “sim_db” from directory: /home/docs/checkouts/readthedocs.org/user_builds/sim-db/checkouts/latest/docs/xml/. Potential matches:

- SimDB *sim_db_ctor_with_id(int id, bool store_metadata)
- type(sim_db) function sim_db_mod::sim_db::sim_db_ctor_with_id (id, store_metadata)
- type(sim_db) function sim_db_mod::sim_db_ctor_with_id (id, store_metadata)

Warning

doxygenfunction: Unable to resolve multiple matches for function “sim_db_ctor_without_search” with arguments (const char*, int, bool) in doxygen xml output for project “sim_db” from directory: /home/docs/checkouts/readthedocs.org/user_builds/sim-db/checkouts/latest/docs/xml/. Potential matches:

- SimDB *sim_db_ctor_without_search(const char *path_proj_root, int id, bool store_metadata)
- type(sim_db) function sim_db_mod::sim_db::sim_db_ctor_without_search (path_proj_root, id, store_metadata)
- type(sim_db) function sim_db_mod::sim_db_ctor_without_search (path_proj_root, id, store_metadata)
int sim_db_read_int(SimDB *self, const char *column)

Read parameter from the database.

Return

Integer read from database.

Parameters
  • self: Return value of sim_db_ctor() or similar functions.

  • column: Name of the parameter and column in the database.

double sim_db_read_double(SimDB *self, const char *column)

Read parameter from the database.

Return

Double read from database.

Parameters
  • self: Return value of sim_db_ctor() or similar functions.

  • column: Name of the parameter and column in the database.

char *sim_db_read_string(SimDB *self, const char *column)

Read parameter from the database.

Return

String read from database. Do NOT free the string, as sim_db_dtor() will do that.

Parameters
  • self: Return value of sim_db_ctor() or similar functions.

  • column: Name of the parameter and column in the database.

bool sim_db_read_bool(SimDB *self, const char *column)

Read parameter from the database.

Return

Bool read from database.

Parameters
  • self: Return value of sim_db_ctor() or similar functions.

  • column: Name of the parameter and column in the database.

struct SimDBIntVec

Vector of integers.

Public Members

size_t size

Length of array.

int *array

Array of integers.

SimDBIntVec sim_db_read_int_vec(SimDB *self, const char *column)

Read parameter from the database.

Return

Vector of integers read from database. Do NOT free array as sim_db_dtor() will do that.

Parameters
  • self: Return value of sim_db_ctor() or similar functions.

  • column: Name of the parameter and column in the database.

struct SimDBDoubleVec

Vector of doubles.

Public Members

size_t size

Length of array.

double *array

Array of doubles.

SimDBDoubleVec sim_db_read_double_vec(SimDB *self, const char *column)

Read parameter from the database.

Return

Vector of doubles read from database. Do NOT free array as sim_db_dtor() will do that.

Parameters
  • self: Return value of sim_db_ctor() or similar functions.

  • column: Name of the parameter and column in the database.

struct SimDBStringVec

Vector of strings.

Public Members

size_t size

Length of array.

char **array

Array of strings.

SimDBStringVec sim_db_read_string_vec(SimDB *self, const char *column)

Read parameter from the database.

Return

Vector of strings read from database. Do NOT free array as sim_db_dtor() will do that.

Parameters
  • self: Return value of sim_db_ctor() or similar functions.

  • column: Name of the parameter and column in the database.

struct SimDBBoolVec

Vector of booleans.

Public Members

size_t size

Length of array.

bool *array

Array of booleans.

SimDBBoolVec sim_db_read_bool_vec(SimDB *self, const char *column)

Read parameter from the database.

Return

Vector of booleans read from database. Do NOT free array as sim_db_dtor() will do that.

Parameters
  • self: Return value of sim_db_ctor() or similar functions.

  • column: Name of the parameter and column in the database.

void sim_db_write_int(SimDB *self, const char *column, int value, bool only_if_empty)

Write value to database.

Parameters
  • self: Return value of sim_db_ctor() or similar functions.

  • column: Name of the column in the database to write to.

  • only_if_empty: If True, it will only write to the database if the simulation’s entry under ‘column’ is empty. Will avoid any potential timeouts for concurrect applications.

void sim_db_write_double(SimDB *self, const char *column, double value, bool only_if_empty)

Write value to database.

Parameters
  • self: Return value of sim_db_ctor() or similar functions.

  • column: Name of the column in the database to write to.

  • only_if_empty: If True, it will only write to the database if the simulation’s entry under ‘column’ is empty. Will avoid any potential timeouts for concurrect applications.

void sim_db_write_string(SimDB *self, const char *column, const char *value, bool only_if_empty)

Write value to database.

Parameters
  • self: Return value of sim_db_ctor() or similar functions.

  • column: Name of the column in the database to write to.

  • only_if_empty: If True, it will only write to the database if the simulation’s entry under ‘column’ is empty. Will avoid any potential timeouts for concurrect applications.

void sim_db_write_bool(SimDB *self, const char *column, bool value, bool only_if_empty)

Write value to database.

Parameters
  • self: Return value of sim_db_ctor() or similar functions.

  • column: Name of the column in the database to write to.

  • only_if_empty: If True, it will only write to the database if the simulation’s entry under ‘column’ is empty. Will avoid any potential timeouts for concurrect applications.

void sim_db_write_int_array(SimDB *self, const char *column, int *arr, size_t len, bool only_if_empty)

Write arr to database.

Parameters
  • self: Return value of sim_db_ctor() or similar functions.

  • column: Name of the column in the database to write to.

  • arr: Array to be written to simulation database.

  • len: Length of arr.

  • only_if_empty: If True, it will only write to the database if the simulation’s entry under ‘column’ is empty. Will avoid any potential timeouts for concurrect applications.

void sim_db_write_double_array(SimDB *self, const char *column, double *arr, size_t len, bool only_if_empty)

Write arr to database.

Parameters
  • self: Return value of sim_db_ctor() or similar functions.

  • column: Name of the column in the database to write to.

  • arr: Array to be written to simulation database.

  • len: Length of arr.

  • only_if_empty: If True, it will only write to the database if the simulation’s entry under ‘column’ is empty. Will avoid any potential timeouts for concurrect applications.

void sim_db_write_string_array(SimDB *self, const char *column, char **arr, size_t len, bool only_if_empty)

Write arr to database.

Parameters
  • self: Return value of sim_db_ctor() or similar functions.

  • column: Name of the column in the database to write to.

  • arr: Array to be written to simulation database.

  • len: Length of arr.

  • only_if_empty: If True, it will only write to the database if the simulation’s entry under ‘column’ is empty. Will avoid any potential timeouts for concurrect applications.

void sim_db_write_bool_array(SimDB *self, const char *column, bool *arr, size_t len, bool only_if_empty)

Write arr to database.

Parameters
  • self: Return value of sim_db_ctor() or similar functions.

  • column: Name of the column in the database to write to.

  • arr: Array to be written to simulation database.

  • len: Length of arr.

  • only_if_empty: If True, it will only write to the database if the simulation’s entry under ‘column’ is empty. Will avoid any potential timeouts for concurrect applications.

char *sim_db_unique_results_dir(SimDB *self, const char *path_to_dir)

Get path to subdirectory in abs_path_to_dir unique to simulation.

The subdirectory will be named ‘date_time_name_id’ and is intended to store results in. If ‘results_dir’ in the database is empty, a new and unique directory is created and the path stored in ‘results_dir’. Otherwise the path in ‘results_dir’ is just returned.

Return

Path to new subdirectory.

Parameters
  • self: Return value of sim_db_ctor() or similar functions.

  • path_to_dir: Path to where the new directory is created. If it starts with ‘root/’, that part will be replaced with the full path to the root directory of the project.

char *sim_db_unique_results_dir_abs_path(SimDB *self, const char *abs_path_to_dir)

Get path to subdirectory in abs_path_to_dir unique to simulation.

The subdirectory will be named ‘date_time_name_id’ and is intended to store results in. If ‘results_dir’ in the database is empty, a new and unique directory is created and the path stored in ‘results_dir’. Otherwise the path in ‘results_dir’ is just returned.

Return

Path to new subdirectory.

Parameters
  • self: Return value of sim_db_ctor() or similar functions.

  • abs_path_to_dir: Absolute path to where the new directory is created.

bool sim_db_column_exists(SimDB *self, const char *column)

Return true if column is a column in the database.

int sim_db_get_id(SimDB *self)

Return ID number of simulation in the database that is connected.

Parameters
  • self: Return value of sim_db_ctor() or similar functions.

char *sim_db_get_path_proj_root(SimDB *self)

Return path to root directory of the project, where *.sim_db/* is located.

Parameters
  • self: Return value of sim_db_ctor() or similar functions.

void sim_db_update_sha1_executables(SimDB *self, char **paths_executables, size_t len, bool only_if_empty)

Save the sha1 hash of the files paths_executables to the database.

Parameters
  • self: Return value of sim_db_ctor() or similar functions.

  • paths_executables: Paths to executable files.

  • len: Length of paths_executables.

  • only_if_empty: If True, it will only write to the database if the simulation’s entry under ‘sha1_executables’ is empty. Will avoid any potential timeouts for concurrect applications.

void sim_db_allow_timeouts(SimDB *self, bool allow_timeouts)

Allow timeouts to occure without exiting if set to true.

A timeout occures after waiting more than 5 seconds to access the database because other threads/processes are busy writing to it. sim_db will exit with an error in that case, unless allow timeouts is set to true. It is false by default. If allowed and a timeout occures the called funciton will have had no effect.

bool sim_db_have_timed_out(SimDB *self)

Checks if a timeout have occured since last call to this function.

void sim_db_delete_from_database(SimDB *self)

Delete simulation from database.

final sim_db_mod::sim_db::sim_db_dtor
SimDB *sim_db_add_empty_sim(bool store_metadata)

Add empty simulation to database and return a SimDB connected to it.

The current working directory and its parent directories will be searched until *.sim_db/* is found.

Return

SimDB of the added simulation.

Parameters
  • store_metadata: Stores metadata if true. Set to ‘false’ for postprocessing (e.g. visualization) of data from simulation.

Warning

doxygenfunction: Unable to resolve multiple matches for function “sim_db_add_empty_sim_without_search” with arguments (const char*, bool) in doxygen xml output for project “sim_db” from directory: /home/docs/checkouts/readthedocs.org/user_builds/sim-db/checkouts/latest/docs/xml/. Potential matches:

- SimDB *sim_db_add_empty_sim_without_search(const char *path_proj_root, bool store_metadata)
- type(sim_db) function sim_db_mod::sim_db_add_empty_sim_without_search (path_proj_root, store_metadata)