Performance tools, initial check-in

Change-Id: I9fb4f4babecbe02d171f38c4d089634e90141937
Signed-off-by: Dave Barach <dave@barachs.net>
diff --git a/perftool/c2cpel.c b/perftool/c2cpel.c
new file mode 100644
index 0000000..38e6fe5
--- /dev/null
+++ b/perftool/c2cpel.c
@@ -0,0 +1,248 @@
+/* 
+ *------------------------------------------------------------------
+ * Copyright (c) 2006-2016 Cisco and/or its affiliates.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/fcntl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <vppinfra/clib.h>
+#include <vppinfra/vec.h>
+#include <vppinfra/hash.h>
+#include <vppinfra/elog.h>
+#include <pwd.h>
+#include <stdarg.h>
+#include <time.h>
+#include "cpel.h"
+#include "cpel_util.h"
+
+static elog_main_t elog_main;
+
+/*
+ * convert_clib_file
+ */
+void convert_clib_file(char *clib_file)
+{
+    clib_error_t *error = 0;
+    int i;
+    elog_main_t *em = &elog_main;
+    double starttime, delta;
+
+    error = elog_read_file (&elog_main, clib_file);
+
+    if (error) {
+        clib_warning("%U", format_clib_error, error);
+        exit (1);
+    }
+
+    em = &elog_main;
+
+    starttime = em->events[0].time;
+
+    for (i = 0; i < vec_len (em->events); i++) {
+        elog_event_t *e;        /* clib event */
+        evt_t *ep;              /* xxx2cpel event */
+        u8 *s;
+        u64 timestamp;
+        elog_event_type_t *t;
+        u8 *brief_event_name;
+        u8 *track_name;
+        int j;
+
+        e = vec_elt_at_index(em->events, i);
+
+        /* Seconds since start of log */
+        delta = e->time - starttime;
+        
+        /* u64 nanoseconds since start of log */
+        timestamp = delta * 1e9;
+
+        s = format (0, "%U%c", format_elog_event, em, e, 0);
+
+        /* allocate an event instance */
+        vec_add2(the_events, ep, 1);
+        ep->timestamp = timestamp;
+        
+        /* convert string event code to a real number */
+        t = vec_elt_at_index (em->event_types, e->type);
+
+        /* 
+         * Construct a reasonable event name.
+         * Truncate the format string at the first whitespace break
+         * or printf format character.
+         */
+        brief_event_name = format (0, "%s", t->format);
+
+        for (j = 0; j < vec_len (brief_event_name); j++) {
+            if (brief_event_name[j] == ' ' ||
+                brief_event_name[j] == '%' ||
+                brief_event_name[j] == '(') {
+                brief_event_name[j] = 0;
+                break;
+            }
+        }
+        /* Throw away that much of the formatted event */
+        vec_delete (s, j+1, 0);
+
+        ep->event_id = find_or_add_event(brief_event_name, "%s");
+
+        track_name = format (0, "%U%c", format_elog_track, em, e, 0);
+
+        ep->track_id = find_or_add_track (track_name);
+
+        ep->datum = find_or_add_strtab(s);
+
+        vec_free (track_name);
+        vec_free(brief_event_name);
+        vec_free(s);
+    }
+}
+
+u8 *vec_basename (char *s)
+{
+    u8 * rv;
+    char *cp = s;
+
+    while (*cp)
+        cp++;
+
+    cp--;
+
+    while (cp > s && *cp != '/')
+        cp--;
+
+    if (cp > s)
+        cp++;
+
+    rv = format (0, "%s", cp);
+    return rv;
+}
+
+
+int event_compare (const void *a0, const void *a1)
+{
+    evt_t *e0 = (evt_t *)a0;
+    evt_t *e1 = (evt_t *)a1;
+
+    if (e0->timestamp < e1->timestamp)
+        return -1;
+    else if (e0->timestamp > e1->timestamp)
+        return 1;
+    return 0;
+}
+
+int main (int argc, char **argv)
+{
+    int curarg=1;
+    char **inputfiles = 0;
+    char *outputfile = 0;
+    FILE *ofp;
+
+    if (argc < 3)
+        goto usage;
+
+    while (curarg < argc) {
+        if (!strncmp(argv[curarg], "--input-file", 3)) {
+            curarg++;
+            if (curarg < argc) {
+                vec_add1 (inputfiles, argv[curarg]);
+                curarg++;
+                continue;
+            }
+            clib_warning("Missing filename after --input-file\n");
+            exit (1);
+        }
+
+        if (!strncmp(argv[curarg], "--output-file", 3)) {
+            curarg ++;
+            if (curarg < argc) {
+                outputfile = argv[curarg];
+                curarg ++;
+                continue;
+            }
+            clib_warning("Missing filename after --output-file\n");
+            exit(1);
+        }
+        vec_add1 (inputfiles, argv[curarg]);
+        curarg++;
+        continue;
+
+    usage:
+        fformat(stderr, 
+                "c2cpel [--input-file] <filename> --output-file <filename>\n");
+        exit(1);
+    }
+
+    if (vec_len(inputfiles) == 0 || outputfile == 0)
+        goto usage;
+        
+    if (vec_len(inputfiles) > 1)
+        goto usage;
+
+    cpel_util_init();
+
+    convert_clib_file (inputfiles[0]);
+
+    ofp = fopen (outputfile, "w");
+    if (ofp == NULL) {
+        clib_unix_warning ("couldn't create %s", outputfile);
+        exit (1);
+    }
+    
+    alpha_sort_tracks();
+    fixup_event_tracks();
+
+    /*
+     * Four sections: string-table, event definitions, track defs, events. 
+     */
+    if (!write_cpel_header(ofp, 4)) {
+        clib_warning ("Error writing cpel header to %s...\n", outputfile);
+        unlink(outputfile);
+        exit(1);
+    }
+
+    if (!write_string_table(ofp)) {
+        clib_warning ("Error writing string table to %s...\n", outputfile);
+        unlink(outputfile);
+        exit(1);
+    }
+
+    if (!write_event_defs(ofp)) {
+        clib_warning ("Error writing event defs to %s...\n", outputfile);
+        unlink(outputfile);
+        exit(1);
+    }
+
+    if (!write_track_defs(ofp)) {
+        clib_warning ("Error writing track defs to %s...\n", outputfile);
+        unlink(outputfile);
+        exit(1);
+    }
+
+    if (!write_events(ofp, (u64) 1e9)) {
+        clib_warning ("Error writing events to %s...\n", outputfile);
+        unlink(outputfile);
+        exit(1);
+        
+    }
+    fclose(ofp);
+    exit (0);
+}