TAUdb C API
TAUdb C API Overview
The C API for TAUdb is currently under development, but there is a beta version of the API available. The API provides the following capabilities:
-
Loading trials from the database
-
Inserting trials into the database
-
Parsing TAU profile files
TAUdb C Structures
The C structures are roughly organized as a tree, with a trial object at the root.
-
taudb_trial: A top-level structure which contains the collections of all the performance data dimensions.
-
taudb_primary_metadata: Name/value pairs which describe the properties of the trial.
-
taudb_secondary_metadata: Name/value pairs which describe the properties of the trial. Unlike primary_metadata values, secondary_metadata objects can have complex value types. They are also associated with a measurement context - a thread of execution, a timer, a timestamp, an iteration, etc.
-
taudb_thread: A structure which represents a thread of execution in the parallel measurement.
-
taudb_time_range: A structure which holds a time-range value of beginning and ending iteration numbers or timestamps.
-
taudb_metric: A structure which represents a unit of measurement, such as TIME, FP_OPS, L1_DCM, etc.
-
taudb_timer: A structure which represents a region of code. For example, a phase, a function, a loop, a basic block, or even a line of code.
-
taudb_timer_parameter: A structure which represents parameter values, when parameter based profiling is used.
-
taudb_timer_group: A structure which represents a semantic grouping of timers, such as "I/O", "MPI", "OpenMP", etc.
-
taudb_timer_callpath: A structure which represents a node in the dynamic callpath tree. Timer_callpaths with a null parent are either top level timers, or a timers in a flat profile.
-
taudb_timer_call_data: A structure which represents a tuple between a thread of execution and a node on the timer callpath tree.
-
taudb_timer_value: A structure which represents a tuple between a timer_call_data object and a metric. The timer_value contains the measurement of one metric for one timer on one thread of execution.
-
taudb_counter: A structure which represents a counter in the profile. For example, the number of bytes transferred on an MPI_Send() timer.
-
taudb_counter_value: A structure which represents a counter measurement on one thread of execution.
Below are the object definitions, from the TAUdb C header file.
#ifndef TAUDB_STRUCTS_H
#define TAUDB_STRUCTS_H 1
#include "time.h"
#include "uthash.h"
#include "taudb_structs.h"
#if defined __TAUDB_POSTGRESQL__
#include "libpq-fe.h"
#elif defined __TAUDB_SQLITE__
#include "sqlite3.h"
#endif
#ifndef boolean
#define TRUE 1
#define FALSE 0
typedef int boolean;
#endif
typedef struct taudb_prepared_statement {
char* name;
UT_hash_handle hh; /* hash index for hashing by name */
} TAUDB_PREPARED_STATEMENT;
/* forward declarations to ease objects that need to know about
* each other and have doubly-linked relationships */
struct taudb_timer_call_data;
struct taudb_timer_value;
struct taudb_timer_callpath;
struct taudb_timer_group;
struct taudb_timer_parameter;
struct taudb_timer;
struct taudb_counter_value;
struct taudb_counter;
struct taudb_primary_metadata;
struct taudb_secondary_metadata;
struct taudb_time_range;
struct taudb_thread;
struct taudb_metric;
struct taudb_trial;
struct perfdmf_experiment;
struct perfdmf_application;
typedef struct taudb_configuration {
char* jdbc_db_type; /* to identify DBMS vendor.
* postgresql, mysql, h2, derby, etc. */
char* db_hostname; /* server host name */
char* db_portnum; /* server port number */
char* db_dbname; /* the database name at the server */
char* db_schemaprefix; /* the schema prefix. This is appended to
* all table names for some DBMSs */
char* db_username; /* the database username */
char* db_password; /* the database password for username */
char* db_schemafile; /* full or relative path to the schema file,
* used for configuration, not used in C API */
} TAUDB_CONFIGURATION;
typedef enum taudb_database_schema_version {
TAUDB_2005_SCHEMA,
TAUDB_2012_SCHEMA
} TAUDB_SCHEMA_VERSION;
typedef struct taudb_data_source {
int id;
char* name;
char*description;
UT_hash_handle hh1; /* hash index for hashing by id */
UT_hash_handle hh2; /* hash index for hashing by name */
} TAUDB_DATA_SOURCE;
typedef struct taudb_connection {
TAUDB_CONFIGURATION *configuration;
#if defined __TAUDB_POSTGRESQL__
PGconn *connection;
PGresult *res;
TAUDB_PREPARED_STATEMENT *statements;
#elif defined __TAUDB_SQLITE__
sqlite3 *connection;
sqlite3_stmt *ppStmt;
int rc;
#endif
TAUDB_SCHEMA_VERSION schema_version;
boolean inTransaction;
boolean inPortal;
TAUDB_DATA_SOURCE* data_sources_by_id;
TAUDB_DATA_SOURCE* data_sources_by_name;
} TAUDB_CONNECTION;
/* these are the derived thread indexes. */
#define TAUDB_MEAN_WITHOUT_NULLS -1
#define TAUDB_TOTAL -2
#define TAUDB_STDDEV_WITHOUT_NULLS -3
#define TAUDB_MIN -4
#define TAUDB_MAX -5
#define TAUDB_MEAN_WITH_NULLS -6
#define TAUDB_STDDEV_WITH_NULLS -7
/* trials are the top level structure */
typedef struct taudb_trial {
/* actual data from the database */
int id;
char* name;
struct taudb_data_source* data_source;
int node_count; /* i.e. number of processes. */
int contexts_per_node; /* rarely used, usually 1. */
int threads_per_context; /* max number of threads per process
* (can be less on individual processes) */
int total_threads; /* total number of threads */
/* arrays of data for this trial */
struct taudb_metric* metrics_by_id;
struct taudb_metric* metrics_by_name;
struct taudb_thread* threads;
struct taudb_time_range* time_ranges;
struct taudb_timer* timers_by_id;
struct taudb_timer* timers_by_name;
struct taudb_timer_group* timer_groups;
struct taudb_timer_callpath* timer_callpaths_by_id;
struct taudb_timer_callpath* timer_callpaths_by_name;
struct taudb_timer_call_data* timer_call_data_by_id;
struct taudb_timer_call_data* timer_call_data_by_key;
struct taudb_counter* counters_by_id;
struct taudb_counter* counters_by_name;
struct taudb_counter_value* counter_values;
struct taudb_primary_metadata* primary_metadata;
struct taudb_secondary_metadata* secondary_metadata;
struct taudb_secondary_metadata* secondary_metadata_by_key;
} TAUDB_TRIAL;
/*********************************************/
/* data dimensions */
/*********************************************/
/* thread represents one physical & logical
* location for a measurement. */
typedef struct taudb_thread {
int id; /* database id, also key to hash */
struct taudb_trial* trial;
int node_rank; /* which process does this thread belong to? */
int context_rank; /* which context? USUALLY 0 */
int thread_rank; /* what is this thread's rank in the process */
int index; /* what is this threads OVERALL index?
* ranges from 0 to trial.thread_count-1 */
struct taudb_secondary_metadata* secondary_metadata;
UT_hash_handle hh;
} TAUDB_THREAD;
/* metrics are things like TIME, PAPI counters, and derived metrics. */
typedef struct taudb_metric {
int id; /* database value, also key to hash */
char* name; /* key to hash hh2 */
boolean derived; /* was this metric measured, or created by a
* post-processing tool? */
UT_hash_handle hh1; /* hash index for hashing by id */
UT_hash_handle hh2; /* hash index for hashing by name */
} TAUDB_METRIC;
/* Time ranges are ways to delimit the profile data within time ranges.
They are also useful for secondary metadata which is associated with
a specific call to a function. */
typedef struct taudb_time_range {
int id; /* database value, also key to hash */
int iteration_start;
int iteration_end;
uint64_t time_start;
uint64_t time_end; /* was this metric measured,
* or created by a post-processing tool? */
UT_hash_handle hh;
} TAUDB_TIME_RANGE;
/* timers are interval timers, capturing some interval value.
* For callpath or phase profiles, the parent refers to the calling
* function or phase. Timers can also be sample locations, or
* phases (dynamic or static), or sample aggregations (intermediate) */
typedef struct taudb_timer {
int id; /* database value, also key to hash */
struct taudb_trial* trial; /* pointer back to trial - NOTE: Necessary? */
char* name; /* the full timer name, can have file, line, etc. */
char* short_name; /* just the function name, for example */
char* source_file; /* what source file does this function live in? */
int line_number; /* what line does the timer start on? */
int line_number_end; /* what line does the timer end on? */
int column_number; /* what column number does the timer start on? */
int column_number_end; /* what column number does the timer end on? */
struct taudb_timer_group* groups; /* hash of groups,
* using group hash handle hh2 */
struct taudb_timer_parameter* parameters; /* array of parameters */
UT_hash_handle trial_hash_by_id; /* hash key for id lookup */
UT_hash_handle trial_hash_by_name; /* hash key for name lookup
* in temporary hash */
UT_hash_handle group_hash_by_name; /* hash key for name lookup
* in timer group */
} TAUDB_TIMER;
/*********************************************/
/* timer related structures */
/*********************************************/
/* timer groups are the groups such as tau_default,
mpi, openmp, tau_phase, tau_callpath, tau_param, etc.
this mapping table allows for nxn mappings between timers
and groups */
typedef struct taudb_timer_group {
char* name;
struct taudb_timer* timers; /* hash of timers,
* using timer hash handle hh3 */
UT_hash_handle trial_hash_by_name; // hash handle for trial
UT_hash_handle timer_hash_by_name; // hash handle for timers
} TAUDB_TIMER_GROUP;
/* timer parameters are parameter based profile values.
an example is foo (x,y) where x=4 and y=10. in that example,
timer would be the index of the timer with the
name 'foo (x,y) <x>=<4> <y>=<10>'. this table would have two
entries, one for the x value and one for the y value.
The parameter can also be a phase / iteration index.
*/
typedef struct taudb_timer_parameter {
char* name;
char* value;
UT_hash_handle hh;
} TAUDB_TIMER_PARAMETER;
/* callpath objects contain the merged dynamic callgraph tree seen
* during execution */
typedef struct taudb_timer_callpath {
int id; /* link back to database, and hash key */
struct taudb_timer* timer; /* which timer is this? */
struct taudb_timer_callpath *parent; /* callgraph parent */
char* name; /* a string which has the aggregated callpath. */
UT_hash_handle hh1; /* hash key for hash by id */
UT_hash_handle hh2; /* hash key for name (a => b => c...) lookup */
} TAUDB_TIMER_CALLPATH;
/* timer_call_data objects are observations of a node of the callgraph
for one of the threads. */
typedef struct taudb_call_data_key {
struct taudb_timer_callpath *timer_callpath; /* link back to database */
struct taudb_thread *thread; /* link back to database, roundabout way */
char* timestamp; /* timestamp in case we are in a snapshot or something */
} TAUDB_TIMER_CALL_DATA_KEY;
typedef struct taudb_timer_call_data {
int id; /* link back to database */
TAUDB_TIMER_CALL_DATA_KEY key; /* hash table key */
int calls; /* number of times this timer was seen */
int subroutines; /* number of timers this timer calls */
struct taudb_timer_value* timer_values;
UT_hash_handle hh1;
UT_hash_handle hh2;
} TAUDB_TIMER_CALL_DATA;
/* finally, timer_values are specific measurements during one of the
observations of the node of the callgraph on a thread. */
typedef struct taudb_timer_value {
struct taudb_metric* metric; /* which metric is this? */
double inclusive; /* the inclusive value of this metric */
double exclusive; /* the exclusive value of this metric */
double inclusive_percentage; /* the inclusive percentage of
* total time of the application */
double exclusive_percentage; /* the exclusive percentage of
* total time of the application */
double sum_exclusive_squared; /* how much variance did we see
* every time we measured this timer? */
char *key; /* hash table key - metric name */
UT_hash_handle hh;
} TAUDB_TIMER_VALUE;
/*********************************************/
/* counter related structures */
/*********************************************/
/* counters measure some counted value. An example would be MPI message size
* for an MPI_Send. */
typedef struct taudb_counter {
int id; /* database reference */
struct taudb_trial* trial;
char* name;
UT_hash_handle hh1; /* hash key for hashing by id */
UT_hash_handle hh2; /* hash key for hashing by name */
} TAUDB_COUNTER;
/* counters are atomic counters, not just interval timers */
typedef struct taudb_counter_value_key {
struct taudb_counter* counter; /* the counter we are measuring */
struct taudb_thread* thread; /* where this measurement is */
struct taudb_timer_callpath* context; /* the calling context (can be null) */
char* timestamp; /* timestamp in case we are in a snapshot or something */
} TAUDB_COUNTER_VALUE_KEY;
typedef struct taudb_counter_value {
TAUDB_COUNTER_VALUE_KEY key;
int sample_count; /* how many times did we see take this count? */
double maximum_value; /* what was the max value we saw? */
double minimum_value; /* what was the min value we saw? */
double mean_value; /* what was the average value we saw? */
double standard_deviation; /* how much variance was there? */
UT_hash_handle hh1; /* hash key for hashing by key */
} TAUDB_COUNTER_VALUE;
/*********************************************/
/* metadata related structures */
/*********************************************/
/* primary metadata is metadata that is not nested, does not
contain unique data for each thread. */
typedef struct taudb_primary_metadata {
char* name;
char* value;
UT_hash_handle hh; /* uses the name as the key */
} TAUDB_PRIMARY_METADATA;
/* primary metadata is metadata that could be nested, could
contain unique data for each thread, and could be an array. */
typedef struct taudb_secondary_metadata_key {
struct taudb_timer_callpath *timer_callpath; /* link back to database */
struct taudb_thread *thread; /* link back to database, roundabout way */
struct taudb_secondary_metadata* parent; /* self-referencing */
struct taudb_time_range* time_range;
char* name;
} TAUDB_SECONDARY_METADATA_KEY;
typedef struct taudb_secondary_metadata {
char* id; /* link back to database */
TAUDB_SECONDARY_METADATA_KEY key;
int num_values; /* can have arrays of data */
char** value;
int child_count;
struct taudb_secondary_metadata* children; /* self-referencing */
UT_hash_handle hh; /* uses the id as a compound key */
UT_hash_handle hh2; /* uses the key as a compound key */
} TAUDB_SECONDARY_METADATA;
/* these are for supporting the older schema */
typedef struct perfdmf_experiment {
int id;
char* name;
struct taudb_primary_metadata* primary_metadata;
} PERFDMF_EXPERIMENT;
typedef struct perfdmf_application {
int id;
char* name;
struct taudb_primary_metadata* primary_metadata;
} PERFDMF_APPLICATION;
#endif /* TAUDB_STRUCTS_H */
TAUdb C API
#ifndef TAUDB_API_H
#define TAUDB_API_H 1
#include "taudb_structs.h"
/* when a "get" function is called, this global has the number of
top-level objects that are returned. */
extern int taudb_numItems;
/* the database version */
extern enum taudb_database_schema_version taudb_version;
/* to connect to the database */
extern TAUDB_CONNECTION* taudb_connect_config(char* config_name);
extern TAUDB_CONNECTION* taudb_connect_config_file(char* config_file_name);
/* test the connection status */
extern int taudb_check_connection(TAUDB_CONNECTION* connection);
/* disconnect from the database */
extern int taudb_disconnect(TAUDB_CONNECTION* connection);
/************************************************/
/* query functions */
/************************************************/
/* functions to support the old database schema - avoid these if you can */
extern PERFDMF_APPLICATION*
perfdmf_query_applications(TAUDB_CONNECTION* connection);
extern PERFDMF_EXPERIMENT*
perfdmf_query_experiments(TAUDB_CONNECTION* connection,
PERFDMF_APPLICATION* application);
extern PERFDMF_APPLICATION*
perfdmf_query_application(TAUDB_CONNECTION* connection, char* name);
extern PERFDMF_EXPERIMENT*
perfdmf_query_experiment(TAUDB_CONNECTION* connection,
PERFDMF_APPLICATION* application, char* name);
extern TAUDB_TRIAL* perfdmf_query_trials(TAUDB_CONNECTION* connection,
PERFDMF_EXPERIMENT* experiment);
/* get the data sources */
extern TAUDB_DATA_SOURCE*
taudb_query_data_sources(TAUDB_CONNECTION* connection);
extern TAUDB_DATA_SOURCE*
taudb_get_data_source_by_id(TAUDB_DATA_SOURCE* data_sources,
const int id);
extern TAUDB_DATA_SOURCE*
taudb_get_data_source_by_name(TAUDB_DATA_SOURCE* data_sources,
const char* name);
/* using the properties set in the filter, find a set of trials */
extern TAUDB_TRIAL*
taudb_query_trials(TAUDB_CONNECTION* connection, boolean complete,
TAUDB_TRIAL* filter);
extern TAUDB_PRIMARY_METADATA*
taudb_query_primary_metadata(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* filter);
extern TAUDB_PRIMARY_METADATA*
taudb_get_primary_metadata_by_name(TAUDB_PRIMARY_METADATA* primary_metadata,
const char* name);
extern TAUDB_SECONDARY_METADATA*
taudb_query_secondary_metadata(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* filter);
/* get the threads for a trial */
extern TAUDB_THREAD*
taudb_query_threads(TAUDB_CONNECTION* connection, TAUDB_TRIAL* trial);
extern TAUDB_THREAD*
taudb_query_derived_threads(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial);
extern TAUDB_THREAD*
taudb_get_thread(TAUDB_THREAD* threads, int thread_index);
extern int taudb_get_total_threads(TAUDB_THREAD* threads);
/* get the metrics for a trial */
extern TAUDB_METRIC*
taudb_query_metrics(TAUDB_CONNECTION* connection, TAUDB_TRIAL* trial);
extern TAUDB_METRIC*
taudb_get_metric_by_name(TAUDB_METRIC* metrics, const char* name);
extern TAUDB_METRIC*
taudb_get_metric_by_id(TAUDB_METRIC* metrics, const int id);
/* get the time_ranges for a trial */
extern TAUDB_TIME_RANGE*
taudb_query_time_range(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial);
extern TAUDB_TIME_RANGE*
taudb_get_time_range(TAUDB_TIME_RANGE* time_ranges, const int id);
/* get the timers for a trial */
extern TAUDB_TIMER*
taudb_query_timers(TAUDB_CONNECTION* connection, TAUDB_TRIAL* trial);
extern TAUDB_TIMER*
taudb_get_timer_by_id(TAUDB_TIMER* timers, int id);
extern TAUDB_TIMER*
taudb_get_trial_timer_by_name(TAUDB_TIMER* timers, const char* id);
extern TAUDB_TIMER*
taudb_get_trial_timer_by_name(TAUDB_TIMER* timers, const char* id);
extern TAUDB_TIMER_GROUP*
taudb_query_timer_groups(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial);
extern void
taudb_parse_timer_group_names(TAUDB_TRIAL* trial, TAUDB_TIMER* timer,
char* group_names);
extern TAUDB_TIMER_GROUP*
taudb_get_timer_group_from_trial_by_name(TAUDB_TIMER_GROUP* timers,
const char* name);
extern TAUDB_TIMER_GROUP*
taudb_get_timer_group_from_timer_by_name(TAUDB_TIMER_GROUP* timers,
const char* name);
extern TAUDB_TIMER_CALLPATH*
taudb_query_timer_callpaths(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial, TAUDB_TIMER* timer);
extern TAUDB_TIMER_CALLPATH*
taudb_get_timer_callpath_by_id(TAUDB_TIMER_CALLPATH* timers, int id);
extern TAUDB_TIMER_CALLPATH*
taudb_get_timer_callpath_by_name(TAUDB_TIMER_CALLPATH* timers,
const char* id);
extern TAUDB_TIMER_CALLPATH*
taudb_query_all_timer_callpaths(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial);
extern char* taudb_get_callpath_string(TAUDB_TIMER_CALLPATH* timer_callpath);
/* get the counters for a trial */
extern TAUDB_COUNTER*
taudb_query_counters(TAUDB_CONNECTION* connection, TAUDB_TRIAL* trial);
extern TAUDB_COUNTER*
taudb_get_counter_by_id(TAUDB_COUNTER* counters, int id);
extern TAUDB_COUNTER*
taudb_get_counter_by_name(TAUDB_COUNTER* counters, const char* id);
extern TAUDB_COUNTER_VALUE*
taudb_query_counter_values(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial);
TAUDB_COUNTER_VALUE*
taudb_get_counter_value(TAUDB_COUNTER_VALUE* counter_values,
TAUDB_COUNTER* counter, TAUDB_THREAD* thread,
TAUDB_TIMER_CALLPATH* context, char* timestamp);
/* get the timer call data for a trial */
extern TAUDB_TIMER_CALL_DATA*
taudb_query_timer_call_data(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial, TAUDB_TIMER_CALLPATH* timer_callpath,
TAUDB_THREAD* thread);
extern TAUDB_TIMER_CALL_DATA*
taudb_query_all_timer_call_data(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial);
extern TAUDB_TIMER_CALL_DATA*
taudb_query_timer_call_data_stats(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial, TAUDB_TIMER_CALLPATH* timer_callpath,
TAUDB_THREAD* thread);
extern TAUDB_TIMER_CALL_DATA*
taudb_query_all_timer_call_data_stats(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial);
extern TAUDB_TIMER_CALL_DATA*
taudb_get_timer_call_data_by_id(TAUDB_TIMER_CALL_DATA* timer_call_data,
int id);
extern TAUDB_TIMER_CALL_DATA*
taudb_get_timer_call_data_by_key(TAUDB_TIMER_CALL_DATA* timer_call_data,
TAUDB_TIMER_CALLPATH* callpath, TAUDB_THREAD* thread, char* timestamp);
/* get the timer values for a trial */
extern TAUDB_TIMER_VALUE*
taudb_query_timer_values(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial, TAUDB_TIMER_CALLPATH* timer_callpath,
TAUDB_THREAD* thread, TAUDB_METRIC* metric);
extern TAUDB_TIMER_VALUE*
taudb_query_timer_stats(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial, TAUDB_TIMER_CALLPATH* timer_callpath,
TAUDB_THREAD* thread, TAUDB_METRIC* metric);
extern TAUDB_TIMER_VALUE*
taudb_query_all_timer_values(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial);
extern TAUDB_TIMER_VALUE*
taudb_query_all_timer_stats(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial);
extern TAUDB_TIMER_VALUE*
taudb_get_timer_value(TAUDB_TIMER_CALL_DATA* timer_call_data,
TAUDB_METRIC* metric);
/* find main */
extern TAUDB_TIMER*
taudb_query_main_timer(TAUDB_CONNECTION* connection, TAUDB_TRIAL* trial);
/* save everything */
extern void taudb_save_trial(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial, boolean update, boolean cascade);
extern void taudb_save_threads(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial, boolean update);
extern void taudb_save_metrics(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial, boolean update);
extern void taudb_save_timers(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial, boolean update);
extern void taudb_save_time_ranges(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial, boolean update);
extern void taudb_save_timer_groups(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial, boolean update);
extern void taudb_save_timer_parameters(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial, boolean update);
extern void taudb_save_timer_callpaths(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial, boolean update);
extern void taudb_save_timer_call_data(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial, boolean update);
extern void taudb_save_timer_values(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial, boolean update);
extern void taudb_save_counters(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial, boolean update);
extern void taudb_save_counter_values(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial, boolean update);
extern void taudb_save_primary_metadata(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial, boolean update);
extern void taudb_save_secondary_metadata(TAUDB_CONNECTION* connection,
TAUDB_TRIAL* trial, boolean update);
/************************************************/
/* memory functions */
/************************************************/
extern char* taudb_strdup(const char* in_string);
extern TAUDB_TRIAL* taudb_create_trials(int count);
extern TAUDB_METRIC* taudb_create_metrics(int count);
extern TAUDB_TIME_RANGE* taudb_create_time_ranges(int count);
extern TAUDB_THREAD* taudb_create_threads(int count);
extern TAUDB_SECONDARY_METADATA* taudb_create_secondary_metadata(int count);
extern TAUDB_PRIMARY_METADATA* taudb_create_primary_metadata(int count);
extern TAUDB_PRIMARY_METADATA* taudb_resize_primary_metadata(int count,
TAUDB_PRIMARY_METADATA* old_primary_metadata);
extern TAUDB_COUNTER* taudb_create_counters(int count);
extern TAUDB_COUNTER_VALUE* taudb_create_counter_values(int count);
extern TAUDB_TIMER* taudb_create_timers(int count);
extern TAUDB_TIMER_PARAMETER* taudb_create_timer_parameters(int count);
extern TAUDB_TIMER_GROUP* taudb_create_timer_groups(int count);
extern TAUDB_TIMER_GROUP* taudb_resize_timer_groups(int count,
TAUDB_TIMER_GROUP* old_groups);
extern TAUDB_TIMER_CALLPATH* taudb_create_timer_callpaths(int count);
extern TAUDB_TIMER_CALL_DATA* taudb_create_timer_call_data(int count);
extern TAUDB_TIMER_VALUE* taudb_create_timer_values(int count);
extern void taudb_delete_trials(TAUDB_TRIAL* trials, int count);
/************************************************/
/* Adding objects to the hierarchy */
/************************************************/
extern void taudb_add_metric_to_trial(TAUDB_TRIAL* trial,
TAUDB_METRIC* metric);
extern void taudb_add_time_range_to_trial(TAUDB_TRIAL* trial,
TAUDB_TIME_RANGE* time_range);
extern void taudb_add_thread_to_trial(TAUDB_TRIAL* trial,
TAUDB_THREAD* thread);
extern void taudb_add_secondary_metadata_to_trial(TAUDB_TRIAL* trial,
TAUDB_SECONDARY_METADATA* secondary_metadata);
extern void taudb_add_secondary_metadata_to_secondary_metadata
(TAUDB_SECONDARY_METADATA* parent, TAUDB_SECONDARY_METADATA* child);
extern void taudb_add_primary_metadata_to_trial(TAUDB_TRIAL* trial,
TAUDB_PRIMARY_METADATA* primary_metadata);
extern void taudb_add_counter_to_trial(TAUDB_TRIAL* trial,
TAUDB_COUNTER* counter);
extern void taudb_add_counter_value_to_trial(TAUDB_TRIAL* trial,
TAUDB_COUNTER_VALUE* counter_value);
extern void taudb_add_timer_to_trial(TAUDB_TRIAL* trial,
TAUDB_TIMER* timer);
extern void taudb_add_timer_parameter_to_trial(TAUDB_TRIAL* trial,
TAUDB_TIMER_PARAMETER* timer_parameter);
extern void taudb_add_timer_group_to_trial(TAUDB_TRIAL* trial,
TAUDB_TIMER_GROUP* timer_group);
extern void taudb_add_timer_to_timer_group(TAUDB_TIMER_GROUP* timer_group,
TAUDB_TIMER* timer);
extern void taudb_add_timer_callpath_to_trial(TAUDB_TRIAL* trial,
TAUDB_TIMER_CALLPATH* timer_callpath);
extern void taudb_add_timer_call_data_to_trial(TAUDB_TRIAL* trial,
TAUDB_TIMER_CALL_DATA* timer_call_data);
extern void taudb_add_timer_value_to_timer_call_data
(TAUDB_TIMER_CALL_DATA* timer_call_data, TAUDB_TIMER_VALUE* timer_value);
/* Profile parsers */
extern TAUDB_TRIAL* taudb_parse_tau_profiles(const char* directory_name);
/* Analysis routines */
extern void taudb_compute_statistics(TAUDB_TRIAL* trial);
/* iterators */
extern TAUDB_DATA_SOURCE*
taudb_next_data_source_by_name_from_connection
(TAUDB_DATA_SOURCE* current);
extern TAUDB_DATA_SOURCE*
taudb_next_data_source_by_id_from_connection
(TAUDB_DATA_SOURCE* current);
extern TAUDB_THREAD*
taudb_next_thread_by_index_from_trial(TAUDB_THREAD* current);
extern TAUDB_METRIC*
taudb_next_metric_by_name_from_trial(TAUDB_METRIC* current);
extern TAUDB_METRIC*
taudb_next_metric_by_id_from_trial(TAUDB_METRIC* current);
extern TAUDB_TIME_RANGE*
taudb_next_time_range_by_id_from_trial(TAUDB_TIME_RANGE* current);
extern TAUDB_TIMER*
taudb_next_timer_by_name_from_trial(TAUDB_TIMER* current);
extern TAUDB_TIMER*
taudb_next_timer_by_id_from_trial(TAUDB_TIMER* current);
extern TAUDB_TIMER*
taudb_next_timer_by_name_from_group(TAUDB_TIMER* current);
extern TAUDB_TIMER_GROUP*
taudb_next_timer_group_by_name_from_trial
(TAUDB_TIMER_GROUP* current);
extern TAUDB_TIMER_GROUP*
taudb_next_timer_group_by_name_from_timer
(TAUDB_TIMER_GROUP* current);
extern TAUDB_TIMER_PARAMETER*
taudb_next_timer_parameter_by_name_from_timer
(TAUDB_TIMER_PARAMETER* current);
extern TAUDB_TIMER_CALLPATH*
taudb_next_timer_callpath_by_name_from_trial
(TAUDB_TIMER_CALLPATH* current);
extern TAUDB_TIMER_CALLPATH*
taudb_next_timer_callpath_by_id_from_trial
(TAUDB_TIMER_CALLPATH* current);
extern TAUDB_TIMER_CALL_DATA*
taudb_next_timer_call_data_by_key_from_trial
(TAUDB_TIMER_CALL_DATA* current);
extern TAUDB_TIMER_CALL_DATA*
taudb_next_timer_call_data_by_id_from_trial
(TAUDB_TIMER_CALL_DATA* current);
extern TAUDB_TIMER_VALUE*
taudb_next_timer_value_by_metric_from_timer_call_data
(TAUDB_TIMER_VALUE* current);
extern TAUDB_COUNTER*
taudb_next_counter_by_name_from_trial(TAUDB_COUNTER* current);
extern TAUDB_COUNTER*
taudb_next_counter_by_id_from_trial(TAUDB_COUNTER* current);
extern TAUDB_COUNTER_VALUE*
taudb_next_counter_value_by_key_from_trial(TAUDB_COUNTER_VALUE* current);
extern TAUDB_PRIMARY_METADATA*
taudb_next_primary_metadata_by_name_from_trial
(TAUDB_PRIMARY_METADATA* current);
extern TAUDB_SECONDARY_METADATA*
taudb_next_secondary_metadata_by_key_from_trial
(TAUDB_SECONDARY_METADATA* current);
extern TAUDB_SECONDARY_METADATA*
taudb_next_secondary_metadata_by_id_from_trial
(TAUDB_SECONDARY_METADATA* current);
#endif /* TAUDB_API_H */
TAUdb C API Examples
Creating a trial and inserting into the database
#include "taudb_api.h"
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include "dump_functions.h"
int main (int argc, char** argv) {
TAUDB_CONNECTION* connection = NULL;
if (argc >= 2) {
connection = taudb_connect_config(argv[1]);
} else {
fprintf(stderr, "Please specify a TAUdb config file.\n");
exit(1);
}
printf("Checking connection...\n");
taudb_check_connection(connection);
// create a trial
TAUDB_TRIAL* trial = taudb_create_trials(1);
trial->name = taudb_strdup("TEST TRIAL");
// set the data source to "other"
trial->data_source = taudb_get_data_source_by_id(
taudb_query_data_sources(connection), 999);
// create some metadata
TAUDB_PRIMARY_METADATA* pm = taudb_create_primary_metadata(1);
pm->name = taudb_strdup("Application");
pm->value = taudb_strdup("Test Application");
taudb_add_primary_metadata_to_trial(trial, pm);
pm = taudb_create_primary_metadata(1);
pm->name = taudb_strdup("Start Time");
pm->value = taudb_strdup("2012-11-07 12:30:00");
taudb_add_primary_metadata_to_trial(trial, pm);
// alternatively, you can allocate the primary metadata in blocks
pm = taudb_create_primary_metadata(10);
pm[0].name = taudb_strdup("ClientID");
pm[0].value = taudb_strdup("joe_user");
taudb_add_primary_metadata_to_trial(trial, &(pm[0]));
pm[1].name = taudb_strdup("hostname");
pm[1].value = taudb_strdup("hopper04");
taudb_add_primary_metadata_to_trial(trial, &(pm[1]));
pm[2].name = taudb_strdup("Operating System");
pm[2].value = taudb_strdup("Linux");
taudb_add_primary_metadata_to_trial(trial, &(pm[2]));
pm[3].name = taudb_strdup("Release");
pm[3].value = taudb_strdup("2.6.32.36-0.5-default");
taudb_add_primary_metadata_to_trial(trial, &(pm[3]));
pm[4].name = taudb_strdup("Machine");
pm[4].value = taudb_strdup("Hopper.nersc.gov");
taudb_add_primary_metadata_to_trial(trial, &(pm[4]));
pm[5].name = taudb_strdup("CPU Cache Size");
pm[5].value = taudb_strdup("512 KB");
taudb_add_primary_metadata_to_trial(trial, &(pm[5]));
pm[6].name = taudb_strdup("CPU Clock Frequency");
pm[6].value = taudb_strdup("800.000 MHz");
taudb_add_primary_metadata_to_trial(trial, &(pm[6]));
pm[7].name = taudb_strdup("CPU Model");
pm[7].value = taudb_strdup("Quad-Core AMD Opteron(tm) Processor 8378");
taudb_add_primary_metadata_to_trial(trial, &(pm[7]));
// create a metric
TAUDB_METRIC* metric = taudb_create_metrics(1);
metric->name = taudb_strdup("TIME");
taudb_add_metric_to_trial(trial, metric);
// create a thread
TAUDB_THREAD* thread = taudb_create_threads(1);
thread->node_rank = 1;
thread->context_rank = 1;
thread->thread_rank = 1;
thread->index = 1;
taudb_add_thread_to_trial(trial, thread);
// create a timer, timer_callpath, timer_call_data, timer_value
TAUDB_TIMER_GROUP* timer_group = taudb_create_timer_groups(1);
TAUDB_TIMER* timer = taudb_create_timers(1);
TAUDB_TIMER_CALLPATH* timer_callpath = taudb_create_timer_callpaths(1);
TAUDB_TIMER_CALL_DATA* timer_call_data = taudb_create_timer_call_data(1);
TAUDB_TIMER_VALUE* timer_value = taudb_create_timer_values(1);
timer->name = taudb_strdup(
"int main(int, char **) [{kernel.c} {134,1}-{207,1}]");
timer->short_name = taudb_strdup("main");
timer->source_file = taudb_strdup("kernel.c");
timer->line_number = 134;
timer->column_number = 1;
timer->line_number_end = 207;
timer->column_number_end = 1;
taudb_add_timer_to_trial(trial, timer);
timer_group->name = taudb_strdup("TAU_DEFAULT");
taudb_add_timer_group_to_trial(trial, timer_group);
taudb_add_timer_to_timer_group(timer_group, timer);
timer_callpath->timer = timer;
timer_callpath->parent = NULL;
taudb_add_timer_callpath_to_trial(trial, timer_callpath);
timer_call_data->key.timer_callpath = timer_callpath;
timer_call_data->key.thread = thread;
timer_call_data->calls = 1;
timer_call_data->subroutines = 0;
taudb_add_timer_call_data_to_trial(trial, timer_call_data);
timer_value->metric = metric;
// 5 seconds, or 5 million microseconds
timer_value->inclusive = 5000000;
timer_value->exclusive = 5000000;
timer_value->inclusive_percentage = 100.0;
timer_value->exclusive_percentage = 100.0;
timer_value->sum_exclusive_squared = 0.0;
taudb_add_timer_value_to_timer_call_data(timer_call_data, timer_value);
// compute stats
printf("Computing Stats...\n");
taudb_compute_statistics(trial);
// save the trial!
printf("Testing inserts...\n");
boolean update = FALSE;
boolean cascade = TRUE;
taudb_save_trial(connection, trial, update, cascade);
printf("Disconnecting...\n");
taudb_disconnect(connection);
printf("Done.\n");
return 0;
}
Querying a trial from the database
#include "taudb_api.h"
#include <stdio.h>
#include <string.h>
void dump_metadata(TAUDB_PRIMARY_METADATA *metadata) {
printf("%d metadata fields:\n", HASH_COUNT(metadata));
TAUDB_PRIMARY_METADATA * current;
for(current = metadata; current != NULL;
current = taudb_next_primary_metadata_by_name_from_trial(current)) {
printf(" %s = %s\n", current->name, current->value);
}
}
void dump_secondary_metadata(TAUDB_SECONDARY_METADATA *metadata) {
printf("%d secondary metadata fields:\n", HASH_COUNT(metadata));
TAUDB_SECONDARY_METADATA * current;
for(current = metadata; current != NULL;
current = taudb_next_secondary_metadata_by_key_from_trial(current)) {
printf(" %s = %s\n", current->key.name, current->value[0]);
}
}
void dump_trial(TAUDB_CONNECTION* connection, TAUDB_TRIAL* filter,
boolean haveTrial) {
TAUDB_TRIAL* trial;
if (haveTrial) {
trial = filter;
} else {
trial = taudb_query_trials(connection, FALSE, filter);
}
TAUDB_TIMER* timer = taudb_query_main_timer(connection, trial);
printf("Trial name: '%s', id: %d, main: '%s'\n\n",
trial->name, trial->id, timer->name);
}
int main (int argc, char** argv) {
printf("Connecting...\n");
TAUDB_CONNECTION* connection = NULL;
if (argc >= 2) {
connection = taudb_connect_config(argv[1]);
} else {
fprintf(stderr, "Please specify a TAUdb config file.\n");
exit(1);
}
printf("Checking connection...\n");
taudb_check_connection(connection);
printf("Testing queries...\n");
int t;
// test the "find trials" method to populate the trial
TAUDB_TRIAL* filter = taudb_create_trials(1);
filter->id = atoi(argv[2]);
TAUDB_TRIAL* trials = taudb_query_trials(connection, TRUE, filter);
int numTrials = taudb_numItems;
for (t = 0 ; t < numTrials ; t = t+1) {
printf(" Trial name: '%s', id: %d\n",
trials[t].name, trials[t].id);
dump_metadata(trials[t].primary_metadata);
dump_secondary_metadata(trials[t].secondary_metadata);
dump_trial(connection, &(trials[t]), TRUE);
}
printf("Disconnecting...\n");
taudb_disconnect(connection);
printf("Done.\n");
return 0;
}