2.3 (revision 117c8d5b)
Usage in writing mode - a simple example

This is a short example of how to use the OTF2 writing interface. This example is available as source code in the file otf2_writer_example.c . See also otf2_openmp_writer_example.c and otf2_pthread_writer_example.c when writing with multiple threads.

First include the OTF2 header.

#include <otf2/otf2.h>

For this example an additional include statement is necessary.

#include <stdlib.h>

Furthermore this example uses a function delivering dummy timestamps. Real world applications will use a timer like clock_gettime.

get_time( void )
{
static uint64_t sequence;
return sequence++;
}

Define a pre and post flush callback. If no memory is left in OTF2's internal memory buffer or the writer handle is closed a memory buffer flushing routine is triggered. The pre flush callback is triggered right before a buffer flush. It needs to return either OTF2_FLUSH to flush the recorded data to a file or OTF2_NO_FLUSH to suppress flushing data to a file. The post flush callback is triggered right after a memory buffer flush. It has to return a current timestamp which is recorded to mark the time spend in a buffer flush. The callbacks are passed via a struct to OTF2.

pre_flush( void* userData,
OTF2_FileType fileType,
OTF2_LocationRef location,
void* callerData,
bool final )
{
return OTF2_FLUSH;
}
post_flush( void* userData,
OTF2_FileType fileType,
OTF2_LocationRef location )
{
return get_time();
}
static OTF2_FlushCallbacks flush_callbacks =
{
.otf2_pre_flush = pre_flush,
.otf2_post_flush = post_flush
};

Now everything is prepared to begin with the main program.

int
main( int argc,
char** argv )
{

Create new archive handle.

OTF2_Archive* archive = OTF2_Archive_Open( "ArchivePath",
"ArchiveName",
1024 * 1024 /* event chunk size */,
4 * 1024 * 1024 /* def chunk size */,

Set the previously defined flush callbacks.

OTF2_Archive_SetFlushCallbacks( archive, &flush_callbacks, NULL );

We will operate in a serial context.

Now we can create the event files. Though physical files aren't created yet.

Get a local event writer for location 0.

OTF2_EvtWriter* evt_writer = OTF2_Archive_GetEvtWriter( archive, 0 );

Write an enter and a leave record for region 0 to the local event writer.

OTF2_EvtWriter_Enter( evt_writer,
NULL,
get_time(),
0 /* region */ );
OTF2_EvtWriter_Leave( evt_writer,
NULL,
get_time(),
0 /* region */ );

Now close the event writer, before closing the event files collectively.

OTF2_Archive_CloseEvtWriter( archive, evt_writer );

After we wrote all of the events we close the event files again.

The local definition files are optional, but create them nevertheless to please the reader.

OTF2_DefWriter* def_writer = OTF2_Archive_GetDefWriter( archive, 0 );
OTF2_Archive_CloseDefWriter( archive, def_writer );

Now write the global definitions by getting a writer object for it.

OTF2_GlobalDefWriter* global_def_writer = OTF2_Archive_GetGlobalDefWriter( archive );

We need to define the clock used for this trace and the overall timestamp range.

1 /* 1 tick per second */,
0 /* epoch */,
2 /* length */ );

Now we can start writing the referenced definitions, starting with the strings.

OTF2_GlobalDefWriter_WriteString( global_def_writer, 0, "" );
OTF2_GlobalDefWriter_WriteString( global_def_writer, 1, "Master Process" );
OTF2_GlobalDefWriter_WriteString( global_def_writer, 2, "Main Thread" );
OTF2_GlobalDefWriter_WriteString( global_def_writer, 3, "MyFunction" );
OTF2_GlobalDefWriter_WriteString( global_def_writer, 4, "Alternative function name (e.g. mangled one)" );
OTF2_GlobalDefWriter_WriteString( global_def_writer, 5, "Computes something" );
OTF2_GlobalDefWriter_WriteString( global_def_writer, 6, "MyHost" );
OTF2_GlobalDefWriter_WriteString( global_def_writer, 7, "node" );

Write definition for the code region which was just entered and left to the global definition writer.

0 /* id */,
3 /* region name */,
4 /* alternative name */,
5 /* description */,
0 /* source file */,
0 /* begin lno */,
0 /* end lno */ );

Write the system tree including a definition for the location group to the global definition writer.

0 /* id */,
6 /* name */,
7 /* class */,
0 /* id */,
1 /* name */,
0 /* system tree */ );

Write a definition for the location to the global definition writer.

0 /* id */,
2 /* name */,
2 /* # events */,
0 /* location group */ );

At the end, close the archive and exit.

OTF2_Archive_Close( archive );
return EXIT_SUCCESS;
}

To compile your program use a command like the following. Note that we need to activate the C99 standard explicitly for GCC.

gcc -std=c99 `otf2-config --cflags` \
-c otf2_writer_example.c \
-o otf2_writer_example.o

Now you can link your program with:

gcc otf2_writer_example.o \
`otf2-config --ldflags` \
`otf2-config --libs` \
-o otf2_writer_example