1 /*
2  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 // This file contains the helper classes for the DataLog APIs. See data_log.h
12 // for the APIs.
13 //
14 // These classes are helper classes used for logging data for offline
15 // processing. Data logged with these classes can conveniently be parsed and
16 // processed with e.g. Matlab.
17 #ifndef WEBRTC_SYSTEM_WRAPPERS_INCLUDE_DATA_LOG_IMPL_H_
18 #define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_DATA_LOG_IMPL_H_
19 
20 #include <map>
21 #include <sstream>
22 #include <string>
23 #include <vector>
24 
25 #include "webrtc/base/platform_thread.h"
26 #include "webrtc/base/scoped_ptr.h"
27 #include "webrtc/typedefs.h"
28 
29 namespace webrtc {
30 
31 class CriticalSectionWrapper;
32 class EventWrapper;
33 class LogTable;
34 class RWLockWrapper;
35 
36 // All container classes need to implement a ToString-function to be
37 // writable to file. Enforce this via the Container interface.
38 class Container {
39  public:
~Container()40   virtual ~Container() {}
41 
42   virtual void ToString(std::string* container_string) const = 0;
43 };
44 
45 template<class T>
46 class ValueContainer : public Container {
47  public:
ValueContainer(T data)48   explicit ValueContainer(T data) : data_(data) {}
49 
ToString(std::string * container_string)50   virtual void ToString(std::string* container_string) const {
51     *container_string = "";
52     std::stringstream ss;
53     ss << data_ << ",";
54     ss >> *container_string;
55   }
56 
57  private:
58   T   data_;
59 };
60 
61 template<class T>
62 class MultiValueContainer : public Container {
63  public:
MultiValueContainer(const T * data,int length)64   MultiValueContainer(const T* data, int length)
65     : data_(data, data + length) {
66   }
67 
ToString(std::string * container_string)68   virtual void ToString(std::string* container_string) const {
69     *container_string = "";
70     std::stringstream ss;
71     for (size_t i = 0; i < data_.size(); ++i)
72       ss << data_[i] << ",";
73     *container_string += ss.str();
74   }
75 
76  private:
77   std::vector<T>  data_;
78 };
79 
80 class DataLogImpl {
81  public:
82   ~DataLogImpl();
83 
84   // The implementation of the CreateLog() method declared in data_log.h.
85   // See data_log.h for a description.
86   static int CreateLog();
87 
88   // The implementation of the StaticInstance() method declared in data_log.h.
89   // See data_log.h for a description.
90   static DataLogImpl* StaticInstance();
91 
92   // The implementation of the ReturnLog() method declared in data_log.h. See
93   // data_log.h for a description.
94   static void ReturnLog();
95 
96   // The implementation of the AddTable() method declared in data_log.h. See
97   // data_log.h for a description.
98   int AddTable(const std::string& table_name);
99 
100   // The implementation of the AddColumn() method declared in data_log.h. See
101   // data_log.h for a description.
102   int AddColumn(const std::string& table_name,
103                 const std::string& column_name,
104                 int multi_value_length);
105 
106   // Inserts a Container into a table with name table_name at the column
107   // with name column_name.
108   // column_name is treated in a case sensitive way.
109   int InsertCell(const std::string& table_name,
110                  const std::string& column_name,
111                  const Container* value_container);
112 
113   // The implementation of the NextRow() method declared in data_log.h. See
114   // data_log.h for a description.
115   int NextRow(const std::string& table_name);
116 
117  private:
118   DataLogImpl();
119 
120   // Initializes the DataLogImpl object, allocates and starts the
121   // thread file_writer_thread_.
122   int Init();
123 
124   // Write all complete rows in every table to file.
125   // This function should only be called by the file_writer_thread_ if that
126   // thread is running to avoid race conditions.
127   void Flush();
128 
129   // Run() is called by the thread file_writer_thread_.
130   static bool Run(void* obj);
131 
132   // This function writes data to file. Note, it blocks if there is no data
133   // that should be written to file availble. Flush is the non-blocking
134   // version of this function.
135   void Process();
136 
137   // Stops the continuous calling of Process().
138   void StopThread();
139 
140   // Collection of tables indexed by the table name as std::string.
141   typedef std::map<std::string, LogTable*> TableMap;
142   typedef rtc::scoped_ptr<CriticalSectionWrapper> CritSectScopedPtr;
143 
144   static CritSectScopedPtr  crit_sect_;
145   static DataLogImpl*       instance_;
146   int                       counter_;
147   TableMap                  tables_;
148   EventWrapper*             flush_event_;
149   // This is a scoped_ptr so that we don't have to create threads in the no-op
150   // impl.
151   rtc::scoped_ptr<rtc::PlatformThread> file_writer_thread_;
152   RWLockWrapper*            tables_lock_;
153 };
154 
155 }  // namespace webrtc
156 
157 #endif  // WEBRTC_SYSTEM_WRAPPERS_INCLUDE_DATA_LOG_IMPL_H_
158