#include <babeltrace/babeltrace.h>
#include <babeltrace/context.h>
+#include <babeltrace/context-internal.h>
+#include <babeltrace/trace-handle.h>
+#include <babeltrace/trace-handle-internal.h>
+#include <babeltrace/trace-collection.h>
+#include <babeltrace/format.h>
+#include <babeltrace/babeltrace-internal.h>
#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
-struct bt_context *bt_context_create(struct trace_collection *tc)
+#include <fts.h>
+#include <fcntl.h> /* For O_RDONLY */
+
+#include <glib.h>
+
+struct bt_context *bt_context_create(void)
{
struct bt_context *ctx;
- ctx = calloc(1, sizeof(struct bt_context));
- if (ctx == NULL) {
- perror("allocating context");
- goto error;
- }
-
- ctx->tc = tc;
+ ctx = g_new0(struct bt_context, 1);
ctx->refcount = 1;
+ /* Negative handle id are errors. */
ctx->last_trace_handle_id = 0;
- return ctx;
+ /* Instanciate the trace handle container */
+ ctx->trace_handles = g_hash_table_new_full(g_direct_hash,
+ g_direct_equal, NULL,
+ (GDestroyNotify) bt_trace_handle_destroy);
+
+ ctx->tc = g_new0(struct trace_collection, 1);
+ init_trace_collection(ctx->tc);
-error:
- return NULL;
+ return ctx;
}
-int bt_context_destroy(struct bt_context *ctx)
+int bt_context_add_trace(struct bt_context *ctx, const char *path,
+ const char *format_name,
+ void (*packet_seek)(struct stream_pos *pos, size_t index,
+ int whence),
+ struct mmap_stream_list *stream_list,
+ FILE *metadata)
{
- if (ctx) {
- if (ctx->refcount >= 1)
- goto ctx_used;
+ struct trace_descriptor *td;
+ struct format *fmt;
+ struct bt_trace_handle *handle;
+ int ret;
+
+ fmt = bt_lookup_format(g_quark_from_string(format_name));
+ if (!fmt) {
+ fprintf(stderr, "[error] [Context] Format \"%s\" unknown.\n\n",
+ format_name);
+ ret = -1;
+ goto end;
+ }
+ if (path) {
+ td = fmt->open_trace(path, O_RDONLY, packet_seek, NULL);
+ if (!td) {
+ fprintf(stderr, "[error] [Context] Cannot open_trace of the format %s .\n\n",
+ path);
+ ret = -1;
+ goto end;
+ }
+ } else {
+ td = fmt->open_mmap_trace(stream_list, packet_seek, metadata);
+ if (!td) {
+ fprintf(stderr, "[error] [Context] Cannot open_trace of the format %s .\n\n",
+ path);
+ ret = -1;
+ goto end;
+ }
+ }
- free(ctx);
+ /* Create an handle for the trace */
+ handle = bt_trace_handle_create(ctx);
+ if (handle < 0) {
+ fprintf(stderr, "[error] [Context] Creating trace handle %s .\n\n",
+ path);
+ ret = -1;
+ goto end;
}
- return 0;
+ handle->format = fmt;
+ handle->td = td;
+ strncpy(handle->path, path, PATH_MAX);
+ handle->path[PATH_MAX - 1] = '\0';
-ctx_used:
- return -1;
+ /* Add new handle to container */
+ g_hash_table_insert(ctx->trace_handles,
+ (gpointer) (unsigned long) handle->id,
+ handle);
+ ret = trace_collection_add(ctx->tc, td);
+ if (ret == 0)
+ return handle->id;
+end:
+ return ret;
}
-int bt_context_get(struct bt_context *ctx)
+void bt_context_remove_trace(struct bt_context *ctx, int handle_id)
{
- if (!ctx)
- return -1;
- ctx->refcount++;
- return 0;
+ struct bt_trace_handle *handle;
+
+ handle = g_hash_table_lookup(ctx->trace_handles,
+ (gpointer) (unsigned long) handle_id);
+ assert(handle != NULL);
+
+ /* Remove from containers */
+ trace_collection_remove(ctx->tc, handle->td);
+ g_hash_table_remove(ctx->trace_handles,
+ (gpointer) (unsigned long) handle_id);
+
+ /* Close the trace */
+ handle->format->close_trace(handle->td);
+
+ /* Destory the handle */
+ bt_trace_handle_destroy(handle);
}
-int bt_context_put(struct bt_context *ctx)
+static
+void bt_context_destroy(struct bt_context *ctx)
{
- if (!ctx)
- return -1;
+ finalize_trace_collection(ctx->tc);
+
+ /* Remote all traces. The g_hash_table_destroy will call
+ * bt_trace_handle_destroy on each elements.
+ */
+ g_hash_table_destroy(ctx->trace_handles);
+
+ /* ctx->tc should always be valid */
+ assert(ctx->tc != NULL);
+ g_free(ctx->tc);
+ g_free(ctx);
+}
+void bt_context_get(struct bt_context *ctx)
+{
+ ctx->refcount++;
+}
+
+void bt_context_put(struct bt_context *ctx)
+{
ctx->refcount--;
if (ctx->refcount == 0)
- return bt_context_destroy(ctx);
- return 0;
+ bt_context_destroy(ctx);
}