DeviceLogCSV.cpp
Go to the documentation of this file.
1 /*
2 MIT LICENSE
3 
4 Copyright (c) 2014-2020 Inertial Sense, Inc. - http://inertialsense.com
5 
6 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions :
7 
8 The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9 
10 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11 */
12 
13 #include <ctime>
14 #include <string>
15 #include <sstream>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <iomanip>
19 #include <iostream>
20 #include <fstream>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stddef.h>
24 #include <climits>
25 
26 #include "ISPose.h"
27 #include "DeviceLogCSV.h"
28 #include "ISFileManager.h"
29 #include "ISDataMappings.h"
30 
31 using namespace std;
32 
33 
34 void cDeviceLogCSV::InitDeviceForWriting(int pHandle, std::string timestamp, std::string directory, uint64_t maxDiskSpace, uint32_t maxFileSize)
35 {
36  m_logs.clear();
37  m_nextId = 0;
38  cDeviceLog::InitDeviceForWriting(pHandle, timestamp, directory, maxDiskSpace, maxFileSize);
39 }
40 
41 
43 {
45 
46  // open the first file for each possible data set
47  m_logs.clear();
48  for (uint32_t id = DID_NULL + 1; id < DID_COUNT; id++)
49  {
50  const char* dataSet = cISDataMappings::GetDataSetName(id);
51  if (dataSet != NULL)
52  {
53  string dataSetRegex = string(dataSet) + "\\.csv$";
54  vector<ISFileManager::file_info_t> infos;
55  vector<string> files;
56  ISFileManager::GetDirectorySpaceUsed(m_directory, dataSetRegex, infos, false, false);
57  if (infos.size() != 0)
58  {
59  cCsvLog log;
60  log.dataId = id;
62  for (size_t i = 0; i < infos.size(); i++)
63  {
64  files.push_back(infos[i].name);
65  }
66  m_currentFiles[id] = files;
67  m_currentFileIndex[id] = 0;
68  while (OpenNewFile(log, true) && !GetNextLineForFile(log)) {}
69  if (log.nextLine.length() != 0)
70  {
71  m_logs[id] = log;
72  }
73  }
74  }
75  }
76 }
77 
78 
80 {
82 
83  for (map<uint32_t, cCsvLog>::iterator i = m_logs.begin(); i != m_logs.end(); i++)
84  {
85  cCsvLog& log = i->second;
86  if (log.pFile)
87  {
88  fclose(log.pFile);
89  log.pFile = NULL;
90  }
91  }
92  m_logs.clear();
93  return true;
94 }
95 
96 
97 bool cDeviceLogCSV::OpenNewFile(cCsvLog& log, bool readonly)
98 {
99  const char* dataSetName = cISDataMappings::GetDataSetName(log.dataId);
100  if (dataSetName == NULL)
101  {
102  return false;
103  }
104 
105  // Close existing file
106  if (log.pFile)
107  {
108  fclose(log.pFile);
109  log.pFile = NULL;
110  }
111 
112  // Ensure directory exists
113  if (m_directory.empty())
114  {
115  return false;
116  }
117 
118  _MKDIR(m_directory.c_str());
119 
120  // Open new file
121  uint32_t serNum = m_devInfo.serialNumber;
122  if (!serNum)
123  {
124  serNum = m_pHandle;
125  }
126 
127  if (readonly)
128  {
129 tryNextFile:
130  {
131  uint32_t index = m_currentFileIndex[log.dataId];
132  vector<string>& files = m_currentFiles[log.dataId];
133  if (index >= files.size())
134  {
135  m_logs.erase(log.dataId);
136  return false;
137  }
138  string currentFile = files[index++];
139  m_currentFileIndex[log.dataId] = index;
140  log.pFile = fopen(currentFile.c_str(), "r");
141  log.fileCount++;
142  struct stat st;
143  stat(currentFile.c_str(), &st);
144  log.fileSize = st.st_size;
145  m_logSize += log.fileSize;
146  if (m_csv.ReadHeaderFromFile(log.pFile, log.dataId, log.columnHeaders) == 0)
147  {
148  goto tryNextFile;
149  }
150  }
151  }
152  else
153  {
154  log.fileCount++;
155  string fileName = GetNewFileName(serNum, log.fileCount, dataSetName);
156  log.pFile = fopen(fileName.c_str(), "w");
157 
158  // Write Header
159  int fileBytes = m_csv.WriteHeaderToFile(log.pFile, log.dataId);
160 
161  // File byte size
162  log.fileSize = fileBytes;
163  m_logSize += fileBytes;
164  }
165 
166  if (log.pFile)
167  {
168 #if LOG_DEBUG_WRITE
169  printf("Opened save file: %s\n", filename.str().c_str());
170 #endif
171  return true;
172  }
173  else
174  {
175 #if LOG_DEBUG_WRITE
176  printf("FAILED to open save file: %s\n", filename.str().c_str());
177 #endif
178  m_logs.erase(log.dataId);
179  return false;
180  }
181 }
182 
183 
185 {
186  if (log.pFile == NULL)
187  {
188  return false;
189  }
190  char lineBuffer[8192];
191  if (fgets(lineBuffer, _ARRAY_BYTE_COUNT(lineBuffer), log.pFile) == NULL)
192  {
193  return false;
194  }
195  log.nextLine = lineBuffer;
196  size_t index = log.nextLine.find(',', 0);
197  if (index < log.nextLine.size())
198  {
199  log.orderId = strtoull(log.nextLine.c_str(), NULL, 10);
200  }
201  else
202  {
203  return false;
204  }
205  return true;
206 }
207 
208 
209 bool cDeviceLogCSV::SaveData(p_data_hdr_t* dataHdr, const uint8_t* dataBuf)
210 {
211  cDeviceLog::SaveData(dataHdr, dataBuf);
212 
213  // Reference current log
214  cCsvLog& log = m_logs[dataHdr->id];
215  log.dataId = dataHdr->id;
216 
217  // Create first file it it doesn't exist, return out if failure
218  if (log.pFile == NULL && (!OpenNewFile(log, false) || log.pFile == NULL))
219  {
220  return false;
221  }
222  else if (dataHdr->id == DID_DEV_INFO)
223  {
224  memcpy(&m_devInfo, dataBuf, sizeof(dev_info_t));
225  }
226 
227  // Write date to file
228  int nBytes = m_csv.WriteDataToFile(++m_nextId, log.pFile, *dataHdr, dataBuf);
229  if (ferror(log.pFile) != 0)
230  {
231  return false;
232  }
233 
234  // File byte size
235  log.fileSize += nBytes;
236  m_logSize += nBytes;
237 
238  if (log.fileSize >= m_maxFileSize)
239  {
240  // Close existing file
241  fclose(log.pFile);
242  log.pFile = NULL;
243  log.fileSize = 0;
244  }
245 
246  return true;
247 }
248 
249 
251 {
252 
253 tryAgain:
254  if (m_logs.size() == 0)
255  {
256  return NULL;
257  }
258 
259  p_data_t* data = NULL;
260  cCsvLog* nextLog = NULL;
261  uint64_t nextId = ULLONG_MAX;
262  for (map<uint32_t, cCsvLog>::iterator i = m_logs.begin(); i != m_logs.end(); )
263  {
264  if (i->second.orderId < nextId)
265  {
266  nextLog = &i->second;
267  nextId = i->second.orderId;
268  }
269  i++;
270  }
271  if (nextLog == NULL)
272  {
273  assert(false);
274  return NULL;
275  }
276  if ((data = ReadDataFromFile(*nextLog)) == NULL)
277  {
278  goto tryAgain;
279  }
280 
282  return data;
283 }
284 
285 
287 {
288  if (log.pFile == NULL)
289  {
290  assert(false);
291  return NULL;
292  }
293  m_dataBuffer.hdr.id = log.dataId;
294  m_dataBuffer.hdr.size = log.dataSize;
295  if (m_csv.StringCSVToData(log.nextLine, m_dataBuffer.hdr, m_dataBuffer.buf, _ARRAY_BYTE_COUNT(m_dataBuffer.buf), log.columnHeaders))
296  {
297  if (m_dataBuffer.hdr.id == DID_DEV_INFO)
298  {
299  memcpy(&m_devInfo, m_dataBuffer.buf, sizeof(dev_info_t));
300  }
301  log.nextLine.clear();
302  while (!GetNextLineForFile(log) && OpenNewFile(log, true)) {}
303  return &m_dataBuffer;
304  }
305  log.nextLine.clear();
306  while (!GetNextLineForFile(log) && OpenNewFile(log, true)) {}
307  return NULL;
308 }
309 
310 
311 void cDeviceLogCSV::SetSerialNumber(uint32_t serialNumber)
312 {
313  m_devInfo.serialNumber = serialNumber;
314 }
315 
316 
317 
static const char * GetDataSetName(uint32_t dataId)
p_data_t * ReadDataFromFile(cCsvLog &log)
filename
uint64_t fileSize
Definition: DeviceLogCSV.h:32
void OnReadData(p_data_t *data)
Definition: DeviceLog.cpp:267
virtual bool CloseAllFiles()
Definition: DeviceLog.cpp:77
void SetSerialNumber(uint32_t serialNumber) OVERRIDE
uint32_t id
Definition: ISComm.h:375
#define printf(...)
#define DID_COUNT
Definition: data_sets.h:138
#define DID_DEV_INFO
Definition: data_sets.h:35
#define NULL
Definition: nm_bsp.h:52
bool GetNextLineForFile(cCsvLog &log)
vector< data_info_t > columnHeaders
Definition: DeviceLogCSV.h:37
virtual bool SaveData(p_data_hdr_t *dataHdr, const uint8_t *dataBuf)
Definition: DeviceLog.cpp:106
uint32_t dataId
Definition: DeviceLogCSV.h:33
bool OpenNewFile(cCsvLog &log, bool readOnly)
virtual void InitDeviceForWriting(int pHandle, string timestamp, string directory, uint64_t maxDiskSpace, uint32_t maxFileSize)
Definition: DeviceLog.cpp:57
#define _ARRAY_BYTE_COUNT(a)
Definition: ISConstants.h:322
uint64_t orderId
Definition: DeviceLogCSV.h:35
static uint32_t GetSize(uint32_t dataId)
void InitDeviceForReading() OVERRIDE
FILE * pFile
Definition: DeviceLogCSV.h:30
bool SaveData(p_data_hdr_t *dataHdr, const uint8_t *dataBuf) OVERRIDE
void InitDeviceForWriting(int pHandle, std::string timestamp, std::string directory, uint64_t maxDiskSpace, uint32_t maxFileSize) OVERRIDE
USBInterfaceDescriptor data
virtual void InitDeviceForReading()
Definition: DeviceLog.cpp:69
#define _MKDIR(dir)
Definition: ISConstants.h:213
uint64_t GetDirectorySpaceUsed(const std::string &directory, bool recursive)
#define DID_NULL
Definition: data_sets.h:34
uint32_t fileCount
Definition: DeviceLogCSV.h:31
p_data_t * ReadData() OVERRIDE
uint32_t dataSize
Definition: DeviceLogCSV.h:34
bool CloseAllFiles() OVERRIDE
string nextLine
Definition: DeviceLogCSV.h:36


inertial_sense_ros
Author(s):
autogenerated on Sat Sep 19 2020 03:19:04