HOPS
HOPS class reference
MHO_BinaryFileInterface.hh
Go to the documentation of this file.
1 #ifndef MHO_BinaryFileInterface_HH__
2 #define MHO_BinaryFileInterface_HH__
3 
5 #include "MHO_ClassIdentity.hh"
6 #include "MHO_FileKey.hh"
8 #include "MHO_Message.hh"
9 #include "MHO_Serializable.hh"
10 #include "MHO_UUIDGenerator.hh"
11 
12 namespace hops
13 {
14 
27 {
28  public:
29  MHO_BinaryFileInterface(): fCollectKeys(false){};
30 
32 
39  {
40  if(fCollectKeys)
41  {
42  return (fObjectStreamer.IsOpenForWrite() && fKeyStreamer.IsOpenForWrite());
43  }
44  else
45  {
46  return fObjectStreamer.IsOpenForWrite();
47  }
48  }
49 
55  bool IsOpenForRead() { return fObjectStreamer.IsOpenForRead(); }
56 
64  bool OpenToWrite(const std::string& obj_filename, const std::string& index_filename = "")
65  {
66  fObjectStreamer.SetFilename(obj_filename);
67  fObjectStreamer.OpenToWrite();
68 
69  if(index_filename != "") //stream keys to a separate index file
70  {
71  fCollectKeys = true;
72  fKeyStreamer.SetFilename(index_filename);
73  fKeyStreamer.OpenToWrite();
74  return fObjectStreamer.IsOpenForWrite() && fKeyStreamer.IsOpenForWrite();
75  }
76 
77  return fObjectStreamer.IsOpenForWrite();
78  }
79 
87  bool OpenToAppend(const std::string& obj_filename, const std::string& index_filename = "")
88  {
89  fObjectStreamer.SetFilename(obj_filename);
90  fObjectStreamer.OpenToAppend();
91 
92  if(index_filename != "") //stream keys to a separate index file
93  {
94  fCollectKeys = true;
95  fKeyStreamer.SetFilename(index_filename);
96  fKeyStreamer.OpenToAppend();
97  return fObjectStreamer.IsOpenForWrite() && fKeyStreamer.IsOpenForWrite();
98  }
99 
100  return fObjectStreamer.IsOpenForWrite();
101  }
102 
109  bool OpenToRead(const std::string& filename)
110  {
111  fObjectStreamer.SetFilename(filename);
112  fObjectStreamer.OpenToRead();
113 
114  return fObjectStreamer.IsOpenForRead();
115  }
116 
124  bool OpenToReadAtOffset(const std::string& filename, uint64_t offset_bytes)
125  {
126  fObjectStreamer.SetFilename(filename);
127  fObjectStreamer.OpenToRead();
128  fObjectStreamer.GetStream().seekg(offset_bytes, std::ios_base::cur);
129  return fObjectStreamer.IsOpenForRead();
130  }
131 
139  bool ExtractIndexFileObjectKeys(const std::string& index_filename, std::vector< MHO_FileKey >& keys)
140  {
141  keys.clear();
142 
143  if(fObjectStreamer.IsOpenForRead() || fObjectStreamer.IsOpenForWrite() || fKeyStreamer.IsOpenForRead() ||
144  fKeyStreamer.IsOpenForRead())
145  {
146  msg_warn("file", "Cannot extract index file keys with active stream. Close open file first." << eom);
147  return false;
148  }
149  else
150  {
151  fKeyStreamer.SetFilename(index_filename);
152  fKeyStreamer.OpenToRead();
153  if(fKeyStreamer.IsOpenForRead())
154  {
155  while(fKeyStreamer.GetStream().good())
156  {
157  MHO_FileKey key;
158  fKeyStreamer >> key;
159  if(fKeyStreamer.GetStream().good())
160  {
161  keys.push_back(key);
162  }
163  }
164  fKeyStreamer.Close();
165  return true;
166  }
167  else
168  {
169  msg_error("file", "Failed to read object keys, file not open for reading." << eom);
170  fKeyStreamer.Close();
171  return false;
172  }
173  }
174  }
175 
184  bool ExtractFileObjectKeys(const std::string& filename, std::vector< MHO_FileKey >& keys)
185  {
186  keys.clear();
187 
188  if(fObjectStreamer.IsOpenForRead() || fObjectStreamer.IsOpenForWrite() || fKeyStreamer.IsOpenForRead() ||
189  fKeyStreamer.IsOpenForRead())
190  {
191  msg_warn("file", "Cannot extract file keys with active stream. Close open file first." << eom);
192  return false;
193  }
194  else
195  {
196  fKeyStreamer.SetFilename(filename);
197  fKeyStreamer.OpenToRead();
198  if(fKeyStreamer.IsOpenForRead())
199  {
200  while(fKeyStreamer.GetStream().good())
201  {
202  MHO_FileKey key;
203  fKeyStreamer >> key;
204  if(fKeyStreamer.GetStream().good()) //make sure we haven't hit EOF
205  {
206  //first check if the sync word matches, if not then we have
207  //gotten off track and are in unknown territory
208  bool key_ok = true;
209  if(key.fSync != MHO_FileKeySyncWord)
210  {
211  key_ok = false;
212  }
213  if(key_ok)
214  {
215  keys.push_back(key);
216  //now skip ahead by the size of the object
217  fKeyStreamer.SkipAhead(key.fSize);
218  }
219  else
220  {
221  msg_error("file",
222  "Failed to read object key, sync word " << key.fSync << " not recognized." << eom);
223  break;
224  }
225  }
226  else
227  {
228  break;
229  } //EOF
230  }
231  fKeyStreamer.Close();
232  return true;
233  }
234  else
235  {
236  msg_error("file", "Failed to read key, file not open for reading." << eom);
237  fKeyStreamer.Close();
238  return false; //non-recoverable error
239  }
240  }
241  Close();
242  }
243 
252  bool ExtractFileObjectKeysAndOffsets(const std::string& filename, std::vector< MHO_FileKey >& keys,
253  std::vector< std::size_t >& byte_offsets)
254  {
255  keys.clear();
256  std::size_t byte_count = 0;
257 
258  if(fObjectStreamer.IsOpenForRead() || fObjectStreamer.IsOpenForWrite() || fKeyStreamer.IsOpenForRead() ||
259  fKeyStreamer.IsOpenForRead())
260  {
261  msg_warn("file", "Cannot extract file keys with active stream. Close open file first." << eom);
262  return false;
263  }
264  else
265  {
266  fKeyStreamer.SetFilename(filename);
267  fKeyStreamer.OpenToRead();
268  if(fKeyStreamer.IsOpenForRead())
269  {
270  while(fKeyStreamer.GetStream().good())
271  {
272  MHO_FileKey key;
273  fKeyStreamer >> key;
274  if(fKeyStreamer.GetStream().good()) //make sure we haven't hit EOF
275  {
276  //first check if the sync word matches, if not then we have
277  //gotten off track and are in unknown territory
278  bool key_ok = true;
279  if(key.fSync != MHO_FileKeySyncWord)
280  {
281  key_ok = false;
282  }
283  if(key_ok)
284  {
285  byte_offsets.push_back(byte_count);
286  keys.push_back(key);
287  byte_count += MHO_FileKeySize + key.fSize;
288  //now skip ahead by the size of the object
289  fKeyStreamer.SkipAhead(key.fSize);
290  }
291  else
292  {
293  msg_error("file",
294  "Failed to read object key, sync word " << key.fSync << " not recognized." << eom);
295  break;
296  }
297  }
298  else
299  {
300  break;
301  } //EOF
302  }
303  fKeyStreamer.Close();
304  return true;
305  }
306  else
307  {
308  msg_error("file", "Failed to read key, file not open for reading." << eom);
309  fKeyStreamer.Close();
310  return false; //non-recoverable error
311  }
312  }
313  Close();
314  }
315 
319  void Close()
320  {
321  fObjectStreamer.Close();
322  if(!(fObjectStreamer.IsClosed()))
323  {
324  msg_error("file", "Failed to close file." << eom);
325  }
326 
327  if(fCollectKeys)
328  {
329  fKeyStreamer.Close();
330  if(!(fKeyStreamer.IsClosed()))
331  {
332  msg_error("file", "Failed to close key/index file." << eom);
333  }
334  }
335  fCollectKeys = false;
336  }
337 
346  template< class XWriteType > bool Write(const XWriteType& obj, const std::string& shortname = "")
347  {
348  if(fObjectStreamer.IsOpenForWrite())
349  {
350  MHO_FileKey key = GenerateObjectFileKey(obj, shortname);
351  fObjectStreamer.ResetByteCount();
352  fObjectStreamer << key;
353  msg_debug("file", "wrote object key of size: " << fObjectStreamer.GetNBytesWritten() << " bytes." << eom);
354  fObjectStreamer.ResetByteCount();
355  fObjectStreamer << obj;
356  msg_debug("file", "wrote object of size: " << fObjectStreamer.GetNBytesWritten() << " bytes." << eom);
357  if(fObjectStreamer.GetStream().good())
358  {
359  if(fCollectKeys && fKeyStreamer.IsOpenForWrite())
360  {
361  fKeyStreamer << key;
362  }
363  return true;
364  }
365  else
366  {
367  msg_error("file", "Failed to write object, stream state returned: " << fObjectStreamer.GetStream().rdstate()
368  << eom);
369  return false;
370  }
371  }
372  else
373  {
374  return false;
375  msg_error("file", "Failed to write object, file not open for writing." << eom);
376  }
377  }
378 
379  //
388  template< class XWriteType > bool Write(const XWriteType& obj, const char* shortname)
389  {
390  std::string sshortname(shortname);
391  return this->Write(obj, sshortname);
392  }
393 
401  template< class XReadType > bool Read(XReadType& obj, MHO_FileKey& obj_key)
402  {
403  if(fObjectStreamer.IsOpenForRead())
404  {
405  MHO_FileKey key;
406  fObjectStreamer >> key;
407  obj_key = key;
408 
409  //first check if the sync word matches, if not then we have
410  //gotten off track and are in unknown territory
411  bool key_ok = true;
412  if(key.fSync != MHO_FileKeySyncWord)
413  {
414  key_ok = false;
415  }
416 
417  fMD5Generator.Initialize();
418  std::string name = MHO_ClassIdentity::ClassName(obj);
419  fMD5Generator << name;
420  fMD5Generator.Finalize();
421  MHO_UUID type_uuid = fMD5Generator.GetDigestAsUUID();
422  if(key.fTypeId != type_uuid)
423  {
424  key_ok = false;
425  }
426 
427  if(key_ok)
428  {
429  obj.SetObjectUUID(obj_key.fObjectId);
430  fObjectStreamer >> obj;
431  if(fObjectStreamer.IsObjectUnknown())
432  {
433  //object version was not recognized, skip this object's data
434  if(key.fSize > sizeof(MHO_ClassVersion))
435  {
436  uint64_t skip_size = key.fSize - sizeof(MHO_ClassVersion);
437  fObjectStreamer.GetStream().seekg(skip_size, std::ios_base::cur);
438  msg_warn("file", "Encountered and skipped an unrecognized version of object with class name: "
439  << name << "." << eom);
440  fObjectStreamer.ResetObjectState(); //reset streamer state for next object
441  return true; //recoverable error
442  }
443  else
444  {
445  msg_error("file", "Encountered object with wrong/corrupt object size");
446  return false; //non-recoverable error
447  }
448  }
449  return true;
450  }
451  else
452  {
453  msg_error("file",
454  "Failed to read object, object type/key mismatch for object of type: " << name << "." << eom);
455  msg_error("file", "Object uuid: " << type_uuid.as_string() << " file key uuid: " << key.fTypeId.as_string()
456  << "." << eom);
457  return false; //non-recoverable error
458  }
459  }
460  else
461  {
462  msg_error("file", "Failed to read object, file not open for reading." << eom);
463  return false; //non-recoverable error
464  }
465  }
466 
467  private:
468  //the file streamer
469  MHO_BinaryFileStreamer fObjectStreamer;
470  MHO_BinaryFileStreamer fKeyStreamer;
471  MHO_UUIDGenerator fUUIDGenerator;
472  MHO_MD5HashGenerator fMD5Generator;
473 
481  template< class XWriteType > MHO_FileKey GenerateObjectFileKey(const XWriteType& obj, const std::string& shortname)
482  {
483  MHO_FileKey key; //sync and label set in constructor
484 
485  //add short name
486  CopyTruncatedString(shortname, key.fName);
487 
488  fMD5Generator.Initialize();
489  std::string name = MHO_ClassIdentity::ClassName(obj);
490  fMD5Generator << name;
491  fMD5Generator.Finalize();
492  key.fTypeId = fMD5Generator.GetDigestAsUUID(); //type uuid
493 
494  key.fObjectId = obj.GetObjectUUID();
495  msg_debug("file", "constructing a file key with object uuid of: " << key.fObjectId.as_string() << eom);
496  //key.fObjectId = fUUIDGenerator.GenerateUUID(); //random uuid of object id
497  key.fSize = obj.GetSerializedSize();
498 
499  return key;
500  }
501 
502  void CopyTruncatedString(const std::string& s, char* arr)
503  {
504  size_t len = s.size();
505  if(MHO_FileKeyNameLength <= len)
506  {
507  len = MHO_FileKeyNameLength;
508  }
509  for(size_t i = 0; i < len; i++)
510  {
511  if(i < s.size())
512  {
513  arr[i] = s[i];
514  }
515  else
516  {
517  arr[i] = '\0';
518  }
519  }
520  }
521 
522  //file object keys, collected as we go
523  bool fCollectKeys;
524 };
525 
526 } // namespace hops
527 
528 #endif
#define msg_debug(xKEY, xCONTENT)
Definition: MHO_Message.hh:297
#define msg_warn(xKEY, xCONTENT)
Definition: MHO_Message.hh:254
#define msg_error(xKEY, xCONTENT)
Definition: MHO_Message.hh:244
Class MHO_BinaryFileInterface.
Definition: MHO_BinaryFileInterface.hh:27
bool Read(XReadType &obj, MHO_FileKey &obj_key)
Reads the object (XReadType) specified by the object file key from the file.
Definition: MHO_BinaryFileInterface.hh:401
bool OpenToWrite(const std::string &obj_filename, const std::string &index_filename="")
Opens a file for writing and optionally opens an index file if provided.
Definition: MHO_BinaryFileInterface.hh:64
bool OpenToRead(const std::string &filename)
Opens a file for reading and checks if it's open.
Definition: MHO_BinaryFileInterface.hh:109
virtual ~MHO_BinaryFileInterface()
Definition: MHO_BinaryFileInterface.hh:31
bool ExtractFileObjectKeysAndOffsets(const std::string &filename, std::vector< MHO_FileKey > &keys, std::vector< std::size_t > &byte_offsets)
pulls out the object keys and the bytes offsets to the key entry of each object from the start of the...
Definition: MHO_BinaryFileInterface.hh:252
bool OpenToAppend(const std::string &obj_filename, const std::string &index_filename="")
Opens a file for appending objects and optionally streams keys to an index file.
Definition: MHO_BinaryFileInterface.hh:87
void Close()
Closes file and key/index streamers if open.
Definition: MHO_BinaryFileInterface.hh:319
bool Write(const XWriteType &obj, const char *shortname)
Writes an object (must inherit from MHO_Serializable) to a file (with optional shortname string - ove...
Definition: MHO_BinaryFileInterface.hh:388
bool Write(const XWriteType &obj, const std::string &shortname="")
Writes an object (must inherit from MHO_Serializable) to a file (with optional shortname string)....
Definition: MHO_BinaryFileInterface.hh:346
bool ExtractFileObjectKeys(const std::string &filename, std::vector< MHO_FileKey > &keys)
reads an object file and extracts the object file keys while skipping over the object data (cannot be...
Definition: MHO_BinaryFileInterface.hh:184
bool OpenToReadAtOffset(const std::string &filename, uint64_t offset_bytes)
Opens a file for reading at a specified byte offset.
Definition: MHO_BinaryFileInterface.hh:124
bool IsOpenForWrite()
Checks if both object and key streamers are open for writing when fCollectKeys is true,...
Definition: MHO_BinaryFileInterface.hh:38
MHO_BinaryFileInterface()
Definition: MHO_BinaryFileInterface.hh:29
bool IsOpenForRead()
Checks if the object streamer is open for reading.
Definition: MHO_BinaryFileInterface.hh:55
bool ExtractIndexFileObjectKeys(const std::string &index_filename, std::vector< MHO_FileKey > &keys)
reads an index file and extracts the object file keys (cannot be actively streaming to another open f...
Definition: MHO_BinaryFileInterface.hh:139
Class MHO_BinaryFileStreamer declare the concrete class which does the work for file streams.
Definition: MHO_BinaryFileStreamer.hh:298
virtual void OpenToWrite() override
Opens a file for binary writing and sets appropriate state.
Definition: MHO_BinaryFileStreamer.cc:39
virtual void OpenToAppend() override
Opens a binary file for appending and sets appropriate file state.
Definition: MHO_BinaryFileStreamer.cc:23
virtual void OpenToRead() override
Opens a file for binary reading and sets appropriate state.
Definition: MHO_BinaryFileStreamer.cc:7
virtual void ResetByteCount() override
Resets byte count to zero.
Definition: MHO_BinaryFileStreamer.hh:348
virtual uint64_t GetNBytesWritten() const override
Getter for N bytes written.
Definition: MHO_BinaryFileStreamer.hh:364
virtual std::fstream & GetStream() override
Getter for fstream object.
Definition: MHO_BinaryFileStreamer.hh:334
virtual void Close() override
Closes the open file if it exists and sets the file state to closed.
Definition: MHO_BinaryFileStreamer.cc:55
Class MHO_FileKey the version-0 size of the file key is (512 bits / 64 bytes), and all of the version...
Definition: MHO_FileKey.hh:57
char fName[MHO_FileKeyNameLength]
Definition: MHO_FileKey.hh:162
MHO_UUID fTypeId
Definition: MHO_FileKey.hh:161
uint32_t fSync
Definition: MHO_FileKey.hh:154
uint64_t fSize
Definition: MHO_FileKey.hh:163
MHO_UUID fObjectId
Definition: MHO_FileKey.hh:160
virtual bool IsOpenForRead()
Checks if a file is open for reading.
Definition: MHO_FileStreamer.hh:99
virtual void ResetObjectState()
Resets the object state to unset.
Definition: MHO_FileStreamer.hh:136
virtual bool IsClosed()
Checks if the file is closed.
Definition: MHO_FileStreamer.hh:114
void SetFilename(const std::string filename)
Setter for filename.
Definition: MHO_FileStreamer.hh:41
virtual bool IsObjectUnknown()
Checks if object state is unknown.
Definition: MHO_FileStreamer.hh:144
virtual void SkipAhead(size_t n_bytes)
Seeks ahead in file by specified number of bytes and updates object state.
Definition: MHO_FileStreamer.hh:152
virtual bool IsOpenForWrite()
Checks if file is open for writing.
Definition: MHO_FileStreamer.hh:84
Class MHO_MD5HashGenerator declares the concrete class which does the work for file streams.
Definition: MHO_MD5HashGenerator.hh:135
void Finalize()
Finalizes the MD5 hash calculation and stores the result in fDigest.
Definition: MHO_MD5HashGenerator.hh:156
MHO_UUID GetDigestAsUUID()
Getter for digest as uuid.
Definition: MHO_MD5HashGenerator.hh:182
void Initialize()
Recursive function to initialize a game state.
Definition: MHO_MD5HashGenerator.hh:144
Definition: MHO_UUIDGenerator.hh:23
Class MHO_UUID - a class for a 16 byte UUID (for object and type identification)
Definition: MHO_UUID.hh:27
std::string as_string() const
Definition: MHO_UUID.hh:125
Definition: MHO_ChannelLabeler.hh:17
uint32_t MHO_ClassVersion
Definition: MHO_ClassIdentity.hh:22
static std::string ClassName()
Returns the class name as a string.
Definition: MHO_ClassIdentity.hh:36