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 
347  template< class XWriteType > bool Write(const XWriteType& obj, const std::string& shortname = "")
348  {
349  if(fObjectStreamer.IsOpenForWrite())
350  {
351  MHO_FileKey key = GenerateObjectFileKey(obj, shortname);
352  fObjectStreamer.ResetByteCount();
353  fObjectStreamer << key;
354  msg_debug("file", "wrote object key of size: " << fObjectStreamer.GetNBytesWritten() << " bytes." << eom);
355  fObjectStreamer.ResetByteCount();
356  fObjectStreamer << obj;
357  msg_debug("file", "wrote object of size: " << fObjectStreamer.GetNBytesWritten() << " bytes." << eom);
358  if(fObjectStreamer.GetStream().good())
359  {
360  if(fCollectKeys && fKeyStreamer.IsOpenForWrite())
361  {
362  fKeyStreamer << key;
363  }
364  return true;
365  }
366  else
367  {
368  msg_error("file", "Failed to write object, stream state returned: " << fObjectStreamer.GetStream().rdstate()
369  << eom);
370  return false;
371  }
372  }
373  else
374  {
375  return false;
376  msg_error("file", "Failed to write object, file not open for writing." << eom);
377  }
378  }
379 
380  //
390  template< class XWriteType > bool Write(const XWriteType& obj, const char* shortname)
391  {
392  std::string sshortname(shortname);
393  return this->Write(obj, sshortname);
394  }
395 
403  template< class XReadType > bool Read(XReadType& obj, MHO_FileKey& obj_key)
404  {
405  if(fObjectStreamer.IsOpenForRead())
406  {
407  MHO_FileKey key;
408  fObjectStreamer >> key;
409  obj_key = key;
410 
411  //first check if the sync word matches, if not then we have
412  //gotten off track and are in unknown territory
413  bool key_ok = true;
414  if(key.fSync != MHO_FileKeySyncWord)
415  {
416  key_ok = false;
417  }
418 
419  fMD5Generator.Initialize();
420  std::string name = MHO_ClassIdentity::ClassName(obj);
421  fMD5Generator << name;
422  fMD5Generator.Finalize();
423  MHO_UUID type_uuid = fMD5Generator.GetDigestAsUUID();
424  if(key.fTypeId != type_uuid)
425  {
426  key_ok = false;
427  }
428 
429  if(key_ok)
430  {
431  obj.SetObjectUUID(obj_key.fObjectId);
432  fObjectStreamer >> obj;
433  if(fObjectStreamer.IsObjectUnknown())
434  {
435  //object version was not recognized, skip this object's data
436  if(key.fSize > sizeof(MHO_ClassVersion))
437  {
438  uint64_t skip_size = key.fSize - sizeof(MHO_ClassVersion);
439  fObjectStreamer.GetStream().seekg(skip_size, std::ios_base::cur);
440  msg_warn("file", "Encountered and skipped an unrecognized version of object with class name: "
441  << name << "." << eom);
442  fObjectStreamer.ResetObjectState(); //reset streamer state for next object
443  return true; //recoverable error
444  }
445  else
446  {
447  msg_error("file", "Encountered object with wrong/corrupt object size");
448  return false; //non-recoverable error
449  }
450  }
451  return true;
452  }
453  else
454  {
455  msg_error("file",
456  "Failed to read object, object type/key mismatch for object of type: " << name << "." << eom);
457  msg_error("file", "Object uuid: " << type_uuid.as_string() << " file key uuid: " << key.fTypeId.as_string()
458  << "." << eom);
459  return false; //non-recoverable error
460  }
461  }
462  else
463  {
464  msg_error("file", "Failed to read object, file not open for reading." << eom);
465  return false; //non-recoverable error
466  }
467  }
468 
469  private:
470  //the file streamer
471  MHO_BinaryFileStreamer fObjectStreamer;
472  MHO_BinaryFileStreamer fKeyStreamer;
473  MHO_UUIDGenerator fUUIDGenerator;
474  MHO_MD5HashGenerator fMD5Generator;
475 
483  template< class XWriteType > MHO_FileKey GenerateObjectFileKey(const XWriteType& obj, const std::string& shortname)
484  {
485  MHO_FileKey key; //sync and label set in constructor
486 
487  //add short name
488  CopyTruncatedString(shortname, key.fName);
489 
490  fMD5Generator.Initialize();
491  std::string name = MHO_ClassIdentity::ClassName(obj);
492  fMD5Generator << name;
493  fMD5Generator.Finalize();
494  key.fTypeId = fMD5Generator.GetDigestAsUUID(); //type uuid
495 
496  key.fObjectId = obj.GetObjectUUID();
497  msg_debug("file", "constructing a file key with object uuid of: " << key.fObjectId.as_string() << eom);
498  //key.fObjectId = fUUIDGenerator.GenerateUUID(); //random uuid of object id
499  key.fSize = obj.GetSerializedSize();
500 
501  return key;
502  }
503 
504  void CopyTruncatedString(const std::string& s, char* arr)
505  {
506  size_t len = s.size();
507  if(MHO_FileKeyNameLength <= len)
508  {
509  len = MHO_FileKeyNameLength;
510  }
511  for(size_t i = 0; i < len; i++)
512  {
513  if(i < s.size())
514  {
515  arr[i] = s[i];
516  }
517  else
518  {
519  arr[i] = '\0';
520  }
521  }
522  }
523 
524  //file object keys, collected as we go
525  bool fCollectKeys;
526 };
527 
528 } // namespace hops
529 
530 #endif
#define msg_debug(xKEY, xCONTENT)
Definition: MHO_Message.hh:291
#define msg_warn(xKEY, xCONTENT)
Definition: MHO_Message.hh:248
#define msg_error(xKEY, xCONTENT)
Definition: MHO_Message.hh:238
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:403
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:390
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:347
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:293
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:343
virtual uint64_t GetNBytesWritten() const override
Getter for N bytes written.
Definition: MHO_BinaryFileStreamer.hh:359
virtual std::fstream & GetStream() override
Getter for fstream object.
Definition: MHO_BinaryFileStreamer.hh:329
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:54
char fName[MHO_FileKeyNameLength]
Definition: MHO_FileKey.hh:158
MHO_UUID fTypeId
Definition: MHO_FileKey.hh:157
uint32_t fSync
Definition: MHO_FileKey.hh:150
uint64_t fSize
Definition: MHO_FileKey.hh:159
MHO_UUID fObjectId
Definition: MHO_FileKey.hh:156
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:135
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:143
virtual void SkipAhead(size_t n_bytes)
Seeks ahead in file by specified number of bytes and updates object state.
Definition: MHO_FileStreamer.hh:151
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:134
void Finalize()
Finalizes the MD5 hash calculation and stores the result in fDigest.
Definition: MHO_MD5HashGenerator.hh:155
MHO_UUID GetDigestAsUUID()
Getter for digest as uuid.
Definition: MHO_MD5HashGenerator.hh:181
void Initialize()
Recursive function to initialize a game state.
Definition: MHO_MD5HashGenerator.hh:143
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_AdhocFlagging.hh:18
uint32_t MHO_ClassVersion
Definition: MHO_ClassIdentity.hh:22
static std::string ClassName()
Returns the class name as a string.
Definition: MHO_ClassIdentity.hh:51