1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Use of this source code is governed by a BSD-style license
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  that can be found in the LICENSE file in the root of the source
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  tree. An additional intellectual property rights grant can be found
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  in the file PATENTS.  All contributing project authors may
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
113c5fc84109e806cd97be2ce6cd720e1cc949f26dphoglund@webrtc.org#include "webrtc/system_wrappers/interface/data_log.h"
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <assert.h>
14c6d6fed3c0a82bb7a09095381b974e8e5eebcb35pbos@webrtc.org
15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <algorithm>
16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <list>
17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
183c5fc84109e806cd97be2ce6cd720e1cc949f26dphoglund@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
193c5fc84109e806cd97be2ce6cd720e1cc949f26dphoglund@webrtc.org#include "webrtc/system_wrappers/interface/event_wrapper.h"
203c5fc84109e806cd97be2ce6cd720e1cc949f26dphoglund@webrtc.org#include "webrtc/system_wrappers/interface/file_wrapper.h"
213c5fc84109e806cd97be2ce6cd720e1cc949f26dphoglund@webrtc.org#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
223c5fc84109e806cd97be2ce6cd720e1cc949f26dphoglund@webrtc.org#include "webrtc/system_wrappers/interface/thread_wrapper.h"
23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc {
25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgDataLogImpl::CritSectScopedPtr DataLogImpl::crit_sect_(
27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionWrapper::CreateCriticalSection());
28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgDataLogImpl* DataLogImpl::instance_ = NULL;
30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// A Row contains cells, which are indexed by the column names as std::string.
32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// The string index is treated in a case sensitive way.
33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgclass Row {
34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org public:
35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  Row();
36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ~Row();
37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Inserts a Container into the cell of the column specified with
39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // column_name.
40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // column_name is treated in a case sensitive way.
41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int InsertCell(const std::string& column_name,
42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 const Container* value_container);
43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Converts the value at the column specified by column_name to a string
45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // stored in value_string.
46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // column_name is treated in a case sensitive way.
47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  void ToString(const std::string& column_name, std::string* value_string);
48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org private:
50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Collection of containers indexed by column name as std::string
51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  typedef std::map<std::string, const Container*> CellMap;
52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CellMap                   cells_;
54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionWrapper*   cells_lock_;
55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org};
56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// A LogTable contains multiple rows, where only the latest row is active for
58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// editing. The rows are defined by the ColumnMap, which contains the name of
59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// each column and the length of the column (1 for one-value-columns and greater
60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// than 1 for multi-value-columns).
61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgclass LogTable {
62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org public:
63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  LogTable();
64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ~LogTable();
65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
66b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Adds the column with name column_name to the table. The column will be a
67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // multi-value-column if multi_value_length is greater than 1.
68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // column_name is treated in a case sensitive way.
69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int AddColumn(const std::string& column_name, int multi_value_length);
70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Buffers the current row while it is waiting to be written to file,
72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // which is done by a call to Flush(). A new row is available when the
73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // function returns
74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  void NextRow();
75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Inserts a Container into the cell of the column specified with
77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // column_name.
78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // column_name is treated in a case sensitive way.
79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int InsertCell(const std::string& column_name,
80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 const Container* value_container);
81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Creates a log file, named as specified in the string file_name, to
83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // where the table will be written when calling Flush().
84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  int CreateLogFile(const std::string& file_name);
85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Write all complete rows to file.
87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // May not be called by two threads simultaneously (doing so may result in
88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // a race condition). Will be called by the file_writer_thread_ when that
89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // thread is running.
90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  void Flush();
91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org private:
93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Collection of multi_value_lengths indexed by column name as std::string
94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  typedef std::map<std::string, int> ColumnMap;
95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  typedef std::list<Row*> RowList;
96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ColumnMap               columns_;
98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  RowList                 rows_[2];
99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  RowList*                rows_history_;
100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  RowList*                rows_flush_;
101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  Row*                    current_row_;
102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  FileWrapper*            file_;
103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  bool                    write_header_;
104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionWrapper* table_lock_;
105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org};
106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgRow::Row()
108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  : cells_(),
109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    cells_lock_(CriticalSectionWrapper::CreateCriticalSection()) {
110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgRow::~Row() {
113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (CellMap::iterator it = cells_.begin(); it != cells_.end();) {
114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    delete it->second;
115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // For maps all iterators (except the erased) are valid after an erase
116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    cells_.erase(it++);
117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  delete cells_lock_;
119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint Row::InsertCell(const std::string& column_name,
122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                    const Container* value_container) {
123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped synchronize(cells_lock_);
124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(cells_.count(column_name) == 0);
125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (cells_.count(column_name) > 0)
126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  cells_[column_name] = value_container;
128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid Row::ToString(const std::string& column_name,
132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                   std::string* value_string) {
133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped synchronize(cells_lock_);
134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  const Container* container = cells_[column_name];
135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (container == NULL) {
136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    *value_string = "NaN,";
137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return;
138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  container->ToString(value_string);
140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgLogTable::LogTable()
143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  : columns_(),
144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rows_(),
145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rows_history_(&rows_[0]),
146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rows_flush_(&rows_[1]),
147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    current_row_(new Row),
148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    file_(FileWrapper::Create()),
149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    write_header_(true),
150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    table_lock_(CriticalSectionWrapper::CreateCriticalSection()) {
151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgLogTable::~LogTable() {
154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (RowList::iterator row_it = rows_history_->begin();
155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       row_it != rows_history_->end();) {
156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    delete *row_it;
157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    row_it = rows_history_->erase(row_it);
158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (ColumnMap::iterator col_it = columns_.begin();
160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       col_it != columns_.end();) {
161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // For maps all iterators (except the erased) are valid after an erase
162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    columns_.erase(col_it++);
163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (file_ != NULL) {
165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    file_->Flush();
166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    file_->CloseFile();
167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    delete file_;
168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  delete current_row_;
170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  delete table_lock_;
171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint LogTable::AddColumn(const std::string& column_name,
174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                        int multi_value_length) {
175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(multi_value_length > 0);
176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (!write_header_) {
177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // It's not allowed to add new columns after the header
178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // has been written.
179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    assert(false);
180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped synchronize(table_lock_);
183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (write_header_)
184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      columns_[column_name] = multi_value_length;
185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    else
186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      return -1;
187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
191b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid LogTable::NextRow() {
192b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped sync_rows(table_lock_);
193b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  rows_history_->push_back(current_row_);
194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  current_row_ = new Row;
195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint LogTable::InsertCell(const std::string& column_name,
198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                         const Container* value_container) {
199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped synchronize(table_lock_);
200b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(columns_.count(column_name) > 0);
201b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (columns_.count(column_name) == 0)
202b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return current_row_->InsertCell(column_name, value_container);
204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint LogTable::CreateLogFile(const std::string& file_name) {
207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (file_name.length() == 0)
208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (file_->Open())
210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  file_->OpenFile(file_name.c_str(),
212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                  false,  // Open with read/write permissions
213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                  false,  // Don't wraparound and write at the beginning when
214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          // the file is full
215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                  true);  // Open as a text file
216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (file_ == NULL)
217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid LogTable::Flush() {
222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ColumnMap::iterator column_it;
223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  bool commit_header = false;
224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (write_header_) {
225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped synchronize(table_lock_);
226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (write_header_) {
227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      commit_header = true;
228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      write_header_ = false;
229b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (commit_header) {
232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (column_it = columns_.begin();
233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         column_it != columns_.end(); ++column_it) {
234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      if (column_it->second > 1) {
235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        file_->WriteText("%s[%u],", column_it->first.c_str(),
236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                         column_it->second);
237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        for (int i = 1; i < column_it->second; ++i)
238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org          file_->WriteText(",");
239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      } else {
240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        file_->WriteText("%s,", column_it->first.c_str());
241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (columns_.size() > 0)
244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      file_->WriteText("\n");
245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Swap the list used for flushing with the list containing the row history
248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // and clear the history. We also create a local pointer to the new
249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // list used for flushing to avoid race conditions if another thread
250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // calls this function while we are writing.
251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // We don't want to block the list while we're writing to file.
252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  {
253b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped synchronize(table_lock_);
254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    RowList* tmp = rows_flush_;
255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rows_flush_ = rows_history_;
256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rows_history_ = tmp;
257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    rows_history_->clear();
258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Write all complete rows to file and delete them
261b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (RowList::iterator row_it = rows_flush_->begin();
262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org       row_it != rows_flush_->end();) {
263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (column_it = columns_.begin();
264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org         column_it != columns_.end(); ++column_it) {
265b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      std::string row_string;
266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      (*row_it)->ToString(column_it->first, &row_string);
267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      file_->WriteText("%s", row_string.c_str());
268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (columns_.size() > 0)
270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      file_->WriteText("\n");
271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    delete *row_it;
272b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    row_it = rows_flush_->erase(row_it);
273b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
274b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint DataLog::CreateLog() {
277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return DataLogImpl::CreateLog();
278b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
279b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid DataLog::ReturnLog() {
281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return DataLogImpl::ReturnLog();
282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgstd::string DataLog::Combine(const std::string& table_name, int table_id) {
285b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  std::stringstream ss;
286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  std::string combined_id = table_name;
287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  std::string number_suffix;
288b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ss << "_" << table_id;
289b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ss >> number_suffix;
290b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  combined_id += number_suffix;
291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  std::transform(combined_id.begin(), combined_id.end(), combined_id.begin(),
292b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                 ::tolower);
293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return combined_id;
294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint DataLog::AddTable(const std::string& table_name) {
297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  DataLogImpl* data_log = DataLogImpl::StaticInstance();
298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (data_log == NULL)
299b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return data_log->AddTable(table_name);
301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
302b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint DataLog::AddColumn(const std::string& table_name,
304b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                       const std::string& column_name,
305b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                       int multi_value_length) {
306b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  DataLogImpl* data_log = DataLogImpl::StaticInstance();
307b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (data_log == NULL)
308b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
309b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return data_log->DataLogImpl::StaticInstance()->AddColumn(table_name,
310b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                                            column_name,
311b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                                            multi_value_length);
312b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint DataLog::NextRow(const std::string& table_name) {
315b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  DataLogImpl* data_log = DataLogImpl::StaticInstance();
316b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (data_log == NULL)
317b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
318b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return data_log->DataLogImpl::StaticInstance()->NextRow(table_name);
319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgDataLogImpl::DataLogImpl()
322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  : counter_(1),
323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tables_(),
324b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    flush_event_(EventWrapper::Create()),
325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    file_writer_thread_(NULL),
326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tables_lock_(RWLockWrapper::CreateRWLock()) {
327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgDataLogImpl::~DataLogImpl() {
330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  StopThread();
331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  Flush();  // Write any remaining rows
332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  delete file_writer_thread_;
333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  delete flush_event_;
334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (TableMap::iterator it = tables_.begin(); it != tables_.end();) {
335b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    delete static_cast<LogTable*>(it->second);
336b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // For maps all iterators (except the erased) are valid after an erase
337b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tables_.erase(it++);
338b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
339b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  delete tables_lock_;
340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
341b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint DataLogImpl::CreateLog() {
343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped synchronize(crit_sect_.get());
344b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (instance_ == NULL) {
345b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    instance_ = new DataLogImpl();
346b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return instance_->Init();
347b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    ++instance_->counter_;
349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint DataLogImpl::Init() {
354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  file_writer_thread_ = ThreadWrapper::CreateThread(
355b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          DataLogImpl::Run,
356b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          instance_,
357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          kHighestPriority,
358b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                          "DataLog");
359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (file_writer_thread_ == NULL)
360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  unsigned int thread_id = 0;
362b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  bool success = file_writer_thread_->Start(thread_id);
363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (!success)
364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
365b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
366b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
367b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
368b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgDataLogImpl* DataLogImpl::StaticInstance() {
369b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return instance_;
370b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
371b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
372b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid DataLogImpl::ReturnLog() {
373b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped synchronize(crit_sect_.get());
374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (instance_ && instance_->counter_ > 1) {
375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    --instance_->counter_;
376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return;
377b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  delete instance_;
379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  instance_ = NULL;
380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint DataLogImpl::AddTable(const std::string& table_name) {
383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  WriteLockScoped synchronize(*tables_lock_);
384b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Make sure we don't add a table which already exists
385b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (tables_.count(table_name) > 0)
386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
387b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  tables_[table_name] = new LogTable();
388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (tables_[table_name]->CreateLogFile(table_name + ".txt") == -1)
389b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
390b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint DataLogImpl::AddColumn(const std::string& table_name,
394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                           const std::string& column_name,
395b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                           int multi_value_length) {
396b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ReadLockScoped synchronize(*tables_lock_);
397b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (tables_.count(table_name) == 0)
398b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
399b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return tables_[table_name]->AddColumn(column_name, multi_value_length);
400b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
401b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
402b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint DataLogImpl::InsertCell(const std::string& table_name,
403b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            const std::string& column_name,
404b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                            const Container* value_container) {
405b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ReadLockScoped synchronize(*tables_lock_);
406b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  assert(tables_.count(table_name) > 0);
407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (tables_.count(table_name) == 0)
408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return tables_[table_name]->InsertCell(column_name, value_container);
410b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
411b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
412b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint DataLogImpl::NextRow(const std::string& table_name) {
413b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ReadLockScoped synchronize(*tables_lock_);
414b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (tables_.count(table_name) == 0)
415b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
416b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  tables_[table_name]->NextRow();
417b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (file_writer_thread_ == NULL) {
418b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Write every row to file as they get complete.
419b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    tables_[table_name]->Flush();
420b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
421b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Signal a complete row
422b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    flush_event_->Set();
423b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
424b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
425b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
426b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
427b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid DataLogImpl::Flush() {
428b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ReadLockScoped synchronize(*tables_lock_);
429b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  for (TableMap::iterator it = tables_.begin(); it != tables_.end(); ++it) {
430b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    it->second->Flush();
431b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
432b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
433b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
434b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool DataLogImpl::Run(void* obj) {
435b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  static_cast<DataLogImpl*>(obj)->Process();
436b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return true;
437b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
438b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
439b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid DataLogImpl::Process() {
440b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Wait for a row to be complete
441b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  flush_event_->Wait(WEBRTC_EVENT_INFINITE);
442b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  Flush();
443b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
444b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
445b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid DataLogImpl::StopThread() {
446b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (file_writer_thread_ != NULL) {
447b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    file_writer_thread_->SetNotAlive();
448b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    flush_event_->Set();
449b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // Call Stop() repeatedly, waiting for the Flush() call in Process() to
450b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // finish.
451b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    while (!file_writer_thread_->Stop()) continue;
452b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
453b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
454b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
455b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}  // namespace webrtc
456