GCC Code Coverage Report
Directory: cvmfs/ Exec Total Coverage
File: cvmfs/tracer.h Lines: 4 6 66.7 %
Date: 2019-02-03 02:48:13 Branches: 2 2 100.0 %

Line Branch Exec Source
1
/**
2
 * This file is part of the CernVM File System.
3
 */
4
5
#ifndef CVMFS_TRACER_H_
6
#define CVMFS_TRACER_H_ 1
7
8
#include <inttypes.h>
9
#include <pthread.h>
10
#include <sys/time.h>
11
12
#include <cstdio>
13
#include <string>
14
15
#include "atomic.h"
16
#include "shortstring.h"
17
#include "util/single_copy.h"
18
19
/**
20
 * Tracer is a thread-safe logging helper.  It uses a ring buffer
21
 * and spawns a helper thread, that flushes the messages onto the disk
22
 * when necessary.  The output file is in csv format.  Usually tracing
23
 * a message is a lock-free process, which therefore should have minimal
24
 * overhead.
25
 *
26
 * This is _not_ supposed to be a debugging system.  It is optimized for
27
 * speed and does not try to gather any additional information (like
28
 * threadid, status of variables, etc.).
29
 *
30
 * Csv output is adapted from libcsv.
31
 *
32
 * \todo If anything goes wrong, the whole thing breaks down on assertion.  This
33
 * might be not desired behavior.
34
 */
35
class Tracer : SingleCopy {
36
 public:
37
  enum TraceEvents {
38
    kEventOpen = 1,
39
    kEventOpenDir,
40
    kEventReadlink,
41
    kEventLookup,
42
    kEventStatFs,
43
    kEventGetAttr,
44
    kEventListAttr,
45
    kEventGetXAttr
46
  };
47
48
  Tracer();
49
  ~Tracer();
50
51
  void Activate(const int buffer_size, const int flush_threshold,
52
                const std::string &trace_file);
53
  void Spawn();
54
  void Flush();
55
5556060
  void inline __attribute__((used)) Trace(const int event,
56
                                          const PathString &path,
57
                                          const std::string &msg)
58
  {
59
5556060
    if (active_) DoTrace(event, path, msg);
60
5563035
  }
61
62
  bool inline __attribute__((used)) IsActive() {
63
    return active_;
64
  }
65
66
 private:
67
  /**
68
   * Code of the first log line in the trace file.
69
   */
70
  static const int kEventStart = -1;
71
  /**
72
   * Code of the lasr log line in the trace file.
73
   */
74
  static const int kEventStop = -2;
75
  /**
76
   * Manual flush
77
   */
78
  static const int kEventFlush = -3;
79
80
  /**
81
   * Contents of a single log line.
82
   */
83
125820
  struct BufferEntry {
84
    /**
85
     * This is currently with milliseconds precision (using gettimeofday).
86
     */
87
    timeval time_stamp;
88
    /**
89
     * arbitrary code, negative codes are reserved for internal use.
90
     */
91
    int code;
92
    PathString path;  /**< The path that is subject to the trace */
93
    std::string msg;
94
  };
95
96
  static void *MainFlush(void *data);
97
  void GetTimespecRel(const int64_t ms, timespec *ts);
98
  int WriteCsvFile(FILE *fp, const std::string &field);
99
  int32_t DoTrace(const int event,
100
                  const PathString &path,
101
                  const std::string &msg);
102
103
  bool active_;
104
  bool spawned_;
105
  std::string trace_file_;
106
  int buffer_size_;
107
  int flush_threshold_;
108
  BufferEntry *ring_buffer_;
109
  /**
110
   * Has the same size as the ring buffer.  If a message is actually copied to the
111
   * ring buffer memory, the respective flag is set to 1.  Flags are reset to 0 by
112
   * the flush thread.
113
   */
114
  atomic_int32 *commit_buffer_;
115
  pthread_t thread_flush_;
116
  pthread_cond_t sig_flush_;
117
  pthread_mutex_t sig_flush_mutex_;
118
  pthread_cond_t sig_continue_trace_;
119
  pthread_mutex_t sig_continue_trace_mutex_;
120
  /**
121
   * Starts with 0 and gets incremented by each call to trace.  Contains the first
122
   * non-used sequence number.
123
   */
124
  atomic_int32 seq_no_;
125
  /**
126
   * Starts with 0 and gets incremented by the flush thread.  Points to the first
127
   * non-flushed message. flushed <= seq_no holds.
128
   */
129
  atomic_int32 flushed_;
130
  atomic_int32 terminate_flush_thread_;
131
  atomic_int32 flush_immediately_;
132
};
133
134
#endif  // CVMFS_TRACER_H_