nidas  v1.2-1520
SyncRecordReader.h
Go to the documentation of this file.
1 // -*- mode: C++; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4; -*-
2 // vim: set shiftwidth=4 softtabstop=4 expandtab:
3 /*
4  ********************************************************************
5  ** NIDAS: NCAR In-situ Data Acquistion Software
6  **
7  ** 2005, Copyright University Corporation for Atmospheric Research
8  **
9  ** This program is free software; you can redistribute it and/or modify
10  ** it under the terms of the GNU General Public License as published by
11  ** the Free Software Foundation; either version 2 of the License, or
12  ** (at your option) any later version.
13  **
14  ** This program is distributed in the hope that it will be useful,
15  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  ** GNU General Public License for more details.
18  **
19  ** The LICENSE.txt file accompanying this software contains
20  ** a copy of the GNU General Public License. If it is not found,
21  ** write to the Free Software Foundation, Inc.,
22  ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  **
24  ********************************************************************
25 */
26 
27 #ifndef NIDAS_DYNLD_RAF_SYNCRECORDREADER_H
28 #define NIDAS_DYNLD_RAF_SYNCRECORDREADER_H
29 
30 #include <deque>
31 
33 #include <nidas/core/SampleTag.h>
34 #include "SyncRecordVariable.h"
35 #include "SyncServer.h"
36 
38 
39 #ifdef SYNC_RECORD_JSON_OUTPUT
40 #include <json/json.h>
41 #endif
42 
43 namespace nidas { namespace dynld { namespace raf {
44 
46 {
47 public:
48  SyncRecHeaderException(const std::string& expect, const std::string& got):
49  nidas::util::Exception("SyncRecHeaderException",
50  std::string("expected: \"") + expect +
51  "\", got: \"" + got + "\"")
52  {
53  }
54  SyncRecHeaderException(const std::string& msg):
55  nidas::util::Exception("SyncRecHeaderException",msg)
56  {
57  }
58 
63  nidas::util::Exception(x)
64  {
65  }
66 };
67 
86 {
87 public:
88 
94  SyncRecordReader(IOChannel* iochan);
95 
101 
102  virtual ~SyncRecordReader();
103 
104  const std::string& getProjectName() const { return projectName; }
105 
106  const std::string& getTailNumber() const { return aircraftName; }
107 
108  const std::string& getFlightName() const { return flightName; }
109 
110  const std::string& getSoftwareVersion() const { return softwareVersion; }
111 
115  time_t getStartTime() const { return startTime; }
116 
120  const std::list<const SyncRecordVariable*> getVariables()
121  throw(nidas::util::Exception);
122 
127  const SyncRecordVariable* getVariable(const std::string& name) const;
128 
133  size_t getNumValues() const { return numDataValues; }
134 
144  size_t read(dsm_time_t* tt, double *ptr,size_t len) throw(nidas::util::IOException);
145 
146  const std::string &
148  {
149  return _header;
150  }
151 
152  virtual bool
153  receive(const Sample *s) throw();
154 
155  virtual void
156  flush() throw();
157 
162  void
163  endOfStream();
164 
165  int
166  getSyncRecOffset(const nidas::core::Variable* var)
168 
169  int
170  getLagOffset(const nidas::core::Variable* var)
171  throw (SyncRecHeaderException);
172 
177  const std::string&
179  {
181  }
182 
183 private:
184 
185  void init();
186 
187  void scanHeader(const Sample* samp);
188 
189  const Sample*
190  nextSample();
191 
194 
199 
200  std::string getQuotedString(std::istringstream& str);
201 
202  void readKeyedQuotedValues(std::istringstream& header)
203  throw(SyncRecHeaderException);
204 
206 
207  std::list<SampleTag*> sampleTags;
208 
209  std::list<const SyncRecordVariable*> variables;
210 
211  std::map<std::string,const SyncRecordVariable*> variableMap;
212 
214 
215  std::string projectName;
216 
217  std::string aircraftName;
218 
219  std::string flightName;
220 
221  std::string softwareVersion;
222 
223  time_t startTime;
224 
225  bool _debug;
226 
227  std::string _header;
228 
230  bool _eoq;
231 
233  std::deque<const Sample*> _syncRecords;
234 
236 
239 
242 };
243 
244 #ifdef SYNC_RECORD_JSON_OUTPUT
245 inline void
246 write_sync_record_header_as_json(std::ostream& json,
247  const std::string& textheader)
248 {
249  Json::Value root;
250 
251  std::istringstream iss(textheader);
252  std::vector<std::string> lines;
253  std::string line;
254  while (getline(iss, line))
255  {
256  // Skip empty lines, especially the last one.
257  if (line.length())
258  {
259  lines.push_back(line);
260  }
261  }
262  Json::Value header;
263  header.resize(lines.size());
264  for (unsigned int i = 0; i < lines.size(); ++i)
265  {
266  header[i] = lines[i];
267  }
268  root["header"] = header;
269  json << root;
270 }
271 
272 
273 std::string
274 json_sync_record_header_as_string(Json::Value& root)
275 {
276  Json::Value& header = root["header"];
277 
278  std::ostringstream oss;
279  for (unsigned int i = 0; i < header.size(); ++i)
280  {
281  oss << header[i].asString() << "\n";
282  }
283  return oss.str();
284 }
285 
286 
287 inline void
288 write_sync_record_data_as_json(std::ostream& json,
289  dsm_time_t tt,
290  const double* rec,
291  size_t numValues)
292 {
293  Json::Value root;
294  root["time"] = Json::UInt64(tt);
295  root["numValues"] = (int)numValues;
296  // Unfortunately the JSON spec does not support NAN, and so
297  // the data values are written as strings. NANs have a
298  // string form like 'nan' which strtod() can reliably
299  // convert back to a double. Likewise for infinity (inf*),
300  // but those are not as likely to be seen in nidas data.
301  Json::Value data;
302  data.resize(numValues);
303  char buf[64];
304  for (unsigned int i = 0; i < numValues; ++i)
305  {
306  snprintf(buf, sizeof(buf), "%.16g", rec[i]);
307  data[i] = buf;
308  }
309  root["data"] = data;
310  json << root;
311 }
312 
313 inline std::string
314 double_to_string(double value)
315 {
316  char buf[64];
317  snprintf(buf, sizeof(buf), "%.16g", value);
318  return buf;
319 }
320 
321 inline
322 Json::Value
323 write_sync_variable_as_json(const SyncRecordVariable* var,
324  dsm_time_t tt,
325  const double* rec)
326 {
327  Json::Value variable;
328  Json::Value values(Json::arrayValue);
329 
330  // Unfortunately the JSON spec does not support NAN, and so
331  // the data values are written as strings. NANs have a
332  // string form like 'nan' which strtod() can reliably
333  // convert back to a double. Likewise for infinity (inf*),
334  // but those are not as likely to be seen in nidas data.
335  size_t varoffset = var->getSyncRecOffset();
336  int irate = (int)ceil(var->getSampleRate());
337  int vlen = var->getLength();
338 
339  values.resize(vlen*irate);
340  for (int i = 0; i < vlen*irate; ++i)
341  {
342  values[i] = double_to_string(rec[varoffset+i]);
343  }
344  variable["name"] = var->getName();
345  variable["values"] = values;
346 
347  size_t lagoffset = var->getLagOffset();
348  // int deltatUsec = (int)rint(USECS_PER_SEC / var->getSampleRate());
349  dsm_time_t vtime = tt;
350  if (!std::isnan(rec[lagoffset]))
351  vtime += (int) rec[lagoffset];
352  variable["time"] = Json::UInt64(vtime);
353  variable["lagoffset"] = double_to_string(rec[lagoffset]);
354  return variable;
355 }
356 
357 inline
358 void
359 write_sync_record_as_json(std::ostream& json, dsm_time_t tt,
360  const double* record, int nvalues,
361  std::vector<const SyncRecordVariable*>& vars)
362 {
363  Json::Value root;
364  root["time"] = Json::UInt64(tt);
365  root["numValues"] = nvalues;
366  Json::Value& data = root["data"];
367  std::vector<const SyncRecordVariable*>::const_iterator it;
368  for (it = vars.begin(); it != vars.end(); ++it)
369  {
370  Json::Value variable = write_sync_variable_as_json(*it, tt, record);
371  data.append(variable);
372  }
373  json << root;
374 }
375 #endif
376 
377 }}} // namespace nidas namespace dynld namespace raf
378 
379 #endif
const std::string & textHeader()
Definition: SyncRecordReader.h:147
const std::list< const SyncRecordVariable * > getVariables()
Get the list of variables in a sync record.
Definition: SyncRecordReader.cc:634
Definition: SyncServer.h:56
std::string flightName
Definition: SyncRecordReader.h:219
An implementation of a SampleInput.
Definition: SampleInputStream.h:172
std::string _header
Definition: SyncRecordReader.h:227
SyncRecHeaderException * headException
Definition: SyncRecordReader.h:205
bool _debug
Definition: SyncRecordReader.h:225
void endOfStream()
Signal the end of the sample stream, meaning EOF is reached once the queue is empty.
Definition: SyncRecordReader.cc:718
long long dsm_time_t
Posix time in microseconds, the number of non-leap microseconds since 1970 Jan 1 00:00 UTC...
Definition: Sample.h:61
Class describing a sampled variable.
Definition: Variable.h:46
const std::string & getProjectName() const
Definition: SyncRecordReader.h:104
void init()
Definition: SyncRecordReader.cc:112
SampleInputStream * inputStream
Definition: SyncRecordReader.h:192
const SyncRecordVariable * getVariable(const std::string &name) const
Get a pointer to a SyncRecordVariable, searching by name.
Definition: SyncRecordReader.cc:643
virtual void flush()
Ask that this SampleClient send out any buffered Samples that it may be holding.
Definition: SyncRecordReader.cc:709
void scanHeader(const Sample *samp)
Definition: SyncRecordReader.cc:207
size_t read(dsm_time_t *tt, double *ptr, size_t len)
Read a sync record.
Definition: SyncRecordReader.cc:568
std::string getQuotedString(std::istringstream &str)
Definition: SyncRecordReader.cc:532
std::list< SampleTag * > sampleTags
Definition: SyncRecordReader.h:207
const std::string & getFlightName() const
Definition: SyncRecordReader.h:108
Pure virtual interface of a client of Samples.
Definition: SampleClient.h:38
SyncRecHeaderException(const SyncRecHeaderException &x)
Copy constructor.
Definition: SyncRecordReader.h:62
SyncRecordReader handles sync samples and provides an interface to access Variables and read sync rec...
Definition: SyncRecordReader.h:85
A Variable associated with a SyncRecord.
Definition: SyncRecordVariable.h:38
const std::string & getConfigName()
After creating a SyncRecordReader on a socket, this method returns the config name from the SampleInp...
Definition: SyncRecordReader.h:178
A channel for Input or Output of data.
Definition: IOChannel.h:64
SyncRecordReader & operator=(const SyncRecordReader &)
No assignment.
size_t getNumValues() const
Get number of data values in a sync record.
Definition: SyncRecordReader.h:133
int throw(SyncRecHeaderException)
Definition: SyncRecordReader.cc:761
Definition: Exception.h:35
const std::string & getSoftwareVersion() const
Definition: SyncRecordReader.h:110
std::deque< const Sample * > _syncRecords
Place to stash sample records received as a SampleClient.
Definition: SyncRecordReader.h:233
nidas::util::Cond _qcond
Definition: SyncRecordReader.h:229
std::map< std::string, const SyncRecordVariable * > variableMap
Definition: SyncRecordReader.h:211
void readKeyedQuotedValues(std::istringstream &header)
Definition: SyncRecordReader.cc:541
virtual ~SyncRecordReader()
Definition: SyncRecordReader.cc:166
std::string softwareVersion
Definition: SyncRecordReader.h:221
std::list< const SyncRecordVariable * > variables
Definition: SyncRecordReader.h:209
SyncRecHeaderException(const std::string &expect, const std::string &got)
Definition: SyncRecordReader.h:48
Definition: SyncRecordReader.h:45
int len
Definition: sing.cc:934
SyncRecHeaderException(const std::string &msg)
Definition: SyncRecordReader.h:54
Interface to a data sample.
Definition: Sample.h:189
bool _eoq
Definition: SyncRecordReader.h:230
Definition: IOException.h:37
time_t startTime
Definition: SyncRecordReader.h:223
A wrapper class for a Posix condition variable.
Definition: ThreadSupport.h:245
Exception(const std::string &type, const std::string &n, const std::string &m)
Definition: Exception.h:41
std::string projectName
Definition: SyncRecordReader.h:215
SyncRecordReader(IOChannel *iochan)
Constructor of a SyncRecordReader to a connected IOChannel.
Definition: SyncRecordReader.cc:64
std::string _sampleStreamConfigName
Definition: SyncRecordReader.h:235
const Sample * nextSample()
Definition: SyncRecordReader.cc:654
const std::string & getTailNumber() const
Definition: SyncRecordReader.h:106
time_t getStartTime() const
Get UNIX time of the start time of data in the SyncRecords.
Definition: SyncRecordReader.h:115
std::string aircraftName
Definition: SyncRecordReader.h:217
bool _read_sync_server
When true, explicitly read from the SyncServer, if given.
Definition: SyncRecordReader.h:198
SyncServer * syncServer
Definition: SyncRecordReader.h:193
size_t numDataValues
Definition: SyncRecordReader.h:213
virtual bool receive(const Sample *s)
Method called to pass a sample to this client.
Definition: SyncRecordReader.cc:684