NeoPZ
TPZPersistenceManager.cpp
Go to the documentation of this file.
2 #include <stddef.h> // for NULL
3 #include "TPZBFileStream.h" // for TPZBFileStream
4 #include "TPZFileStream.h" // for TPZFileStream
5 #include "TPZGeneralFStream.h" // for TPZGeneralFStream
6 #include "TPZSavable.h" // for TPZSavable
7 #include "pzerror.h" // for DebugStop, PZError
8 #include "pzvec.h"
9 #include "TPZContBufferedStream.h" // for TPZVec
10 #include "TPZChunkInTranslation.h"
11 #include "TPZChunkTranslator.h"
12 #include <algorithm>
13 
14 //#define VerboseMode_Q
15 
16 using namespace TPZPersistenceManagerNS;
17 
19 
20 // for READING from file
25 std::list<std::map < std::string, uint64_t>> TPZPersistenceManager::mVersionHistory;
26 
27 // for WRITING to file
28 std::map<std::string, uint64_t> TPZPersistenceManager::mFileVersionInfo;
32 std::map<const TPZSavable *, int64_t> TPZPersistenceManager::mObjMap;
34 
36  mpStream = NULL;
37  mObjVec.Resize(0);
38  mObjMap.clear();
39 }
40 
41 /********************************************************************
42  * *
43  * WRITE-RELATED METHODS *
44  * *
45  ********************************************************************/
46 void TPZPersistenceManager::OpenWrite(const std::string &fileName,
47  const streamType cStreamType) {
48 
49  switch (cStreamType) {
50  case binary:
51  {
52  mpStream = new TPZBFileStream();
53  break;
54  }
55  case ascii:
56  {
57  mpStream = new TPZFileStream();
58  break;
59  }
60  default:
61  DebugStop();
62  }
63 
64  mpStream->OpenWrite(fileName);
65 
66  std::string versionString("FileVersion");
67  mpStream->Write(versionString.c_str(), 11);
68 
69 #ifdef PZDEBUG
70  if (!mpStream->AmIOpenForWrite()) {
71  DebugStop();
72  }
73  if (mPointersToSave.size() > 0) {
74  DebugStop();
75  }
76 #endif
77  mFileVersionInfo.clear();
78  mObjectsStream.clear();
79  mObjMap.clear();
80  mPointersToSave.clear();
81  mMainObjIds.clear();
82  mNextPointerToSave = 0;
83 }
84 
86  auto objId = ScheduleToWrite(obj);
87  unsigned int nMainObjIds = mMainObjIds.size();
88  mMainObjIds.resize(nMainObjIds + 1);
89  mMainObjIds[nMainObjIds] = objId;
90 
91 #ifdef PZDEBUG
92  uint64_t written = 0x46;
93 #endif
94  for (; mNextPointerToSave < mPointersToSave.size(); ++mNextPointerToSave) {
95  // writes obj-id
96  mObjectsStream.Write(&mNextPointerToSave, 1);
97  auto pointer = mPointersToSave[mNextPointerToSave];
98  // writes classId
99  auto classId = pointer->ClassId();
100  if (classId == -1 || classId == 666) {
101  DebugStop();
102  }
103  mObjectsStream.Write(&classId, 1);
104  // writes object data
105  mCurrentObjectStream.clear();
106  pointer->Write(mCurrentObjectStream, 0);
107  unsigned int size = mCurrentObjectStream.Size();
108  mObjectsStream.Write(&size, 1);
109  mObjectsStream << mCurrentObjectStream;
110 #ifdef PZDEBUG
111 #ifdef VerboseMode_Q
112  std::cout << " ObjId: " << mNextPointerToSave
113  << " Class name: " << typeid(*pointer).name()
114  << " ClassId: " << classId
115  << " range: " << written + 1 << " (0x" << std::hex << written + 1 << std::dec << ") - "
116  << written + sizeof (int64_t) + 2 * sizeof (int) +size
117  << "(0x" << std::hex << written + sizeof (int64_t) + 2 * sizeof (int) +size << ")" << std::dec
118  << " size: " << size << std::endl;
119  written += sizeof (int64_t) + 2 * sizeof (int) +size;
120 #endif
121 #endif
122  }
123 }
124 
126 
127  bool check_Q = false;
128  for (auto item : mFileVersionInfo) {
129  if(item.first.compare("NeoPZ") == 0){
130  check_Q = true;
131  }
132  }
133  if (!check_Q) {
134  mFileVersionInfo.insert(TPZSavable::NeoPZVersion());
135  }
136 
137  mpStream->Write(mFileVersionInfo);
138 
139  const uint64_t nObjects = mPointersToSave.size();
140  mpStream->Write(&nObjects);
141 
142  size_t nObjectBytes = mObjectsStream.Size();
143  char *temp = new char[nObjectBytes];
144  mObjectsStream.GetDataFromBuffer(temp);
145  mpStream->Write(temp, nObjectBytes);
146  delete[] temp;
147 
148  unsigned int nMainObjects = mMainObjIds.size();
149  mpStream->Write(&nMainObjects);
150  for (auto mainObjId : mMainObjIds) {
151  mpStream->Write(&mainObjId);
152  }
153 
154  mpStream->CloseWrite();
155  mFileVersionInfo.clear();
156  mObjectsStream.clear();
157  mObjMap.clear();
158  mPointersToSave.clear();
159  mMainObjIds.clear();
160  mNextPointerToSave = 0;
161 }
162 
164  if (!obj) return -1;
165  auto iMap = mObjMap.find(obj);
166  int64_t objId;
167  if (iMap == mObjMap.end()) { //object isn't in the map yet
168  objId = mObjMap.size();
169  if (mPointersToSave.size() != objId) {
170  DebugStop();
171  }
172  mObjMap.insert(std::make_pair(obj, objId));
173  mFileVersionInfo.insert(obj->Version());
174  mPointersToSave.resize(objId + 1);
175  mPointersToSave[objId] = obj;
176  } else {
177  objId = iMap->second;
178  }
179  return objId;
180 }
181 
183  const int64_t objId = ScheduleToWrite(obj);
184  stream->Write(&objId);
185 }
186 
187 /********************************************************************
188  * *
189  * READ-RELATED METHODS *
190  * *
191  ********************************************************************/
192 
193 void TPZPersistenceManager::TranslateNextPointer(TPZChunkInTranslation& chunk, const std::map<std::string, uint64_t>& toVersion) {
194  int64_t objId;
195  chunk.mOldStream.Read(&objId);
196  chunk.mNewStream.Write(&objId);
197 }
198 
199 void TPZPersistenceManager::TranslatePointers(TPZChunkInTranslation& chunk, const std::map<std::string, uint64_t>& toVersion) {
200  uint64_t size;
201  chunk.mOldStream.Read(&size);
202  chunk.mNewStream.Write(&size);
203  for (uint64_t i = 0; i < size; ++i) {
204  TranslateNextPointer(chunk, toVersion);
205  }
206 }
207 
208 unsigned int TPZPersistenceManager::OpenRead(const std::string &fileName,
209  const streamType cStreamType) {
210 
211  if (TPZSavable::ClassIdMap().size() == 0) {
212  //@TODO parallelize
213  for (const auto &restoreClass : TPZSavable::RestoreClassSet()) {
214 #ifdef VerboseMode_Q
215  std::cout << "Class : " << restoreClass->Restore()->ClassId() << " -> " << typeid(*restoreClass->Restore()).name() << std::endl;
216  if (restoreClass->GetTranslator()){
217  std::cout << "Translator : " << typeid(*restoreClass->GetTranslator()).name() << std::endl;
218  }
219  std::cout << std::endl;
220 #endif
221  TPZSavable *savable = restoreClass->Restore();
222  //@TODO ensure thread-safety
223  int classid = savable->ClassId();
224 #ifdef VerboseMode_Q
225  std::cout << " Class being registered with classid = " << classid << std::endl;
226  std::cout << std::endl;
227 #endif
228  TPZSavable::RegisterClassId(classid, restoreClass);
229  auto objHistory = savable->VersionHistory();
230  for (auto versionMap : objHistory) {
231  if (std::find(mVersionHistory.begin(), mVersionHistory.end(), versionMap) == mVersionHistory.end()) {
232  mVersionHistory.push_back(versionMap);
233  }
234  }
235  }
236 
237  std::list<std::map < std::string, uint64_t>> mapsToRemove;
238  for (auto versionMap : mVersionHistory) {
239  for (auto otherMap : mVersionHistory) {
240  if (otherMap == versionMap) {
241  continue;
242  }
243  if (std::search(otherMap.begin(), otherMap.end(), versionMap.begin(), versionMap.end()) != otherMap.end()) {
244  mapsToRemove.push_back(versionMap);
245  break;
246  }
247  }
248  }
249  for (auto mapToRemove : mapsToRemove) {
250  mVersionHistory.remove(mapToRemove);
251  }
252  }
253 
254  switch (cStreamType) {
255  case binary:
256  {
257  mpStream = new TPZBFileStream();
258  break;
259  }
260  case ascii:
261  {
262  mpStream = new TPZFileStream();
263  break;
264  }
265  default:
266  DebugStop();
267  }
268  mpStream->OpenRead(fileName);
269  std::string versionString("FileVersion");
270  char versionRead[12];
271  mpStream->Read(versionRead, 11);
272  versionRead[11] = '\0'; // terminates c-style string
273 
274  if (versionString.compare(versionRead) != 0) { // unversioned file --- not readable
275  PZError << "Error reading file - unversioned file" << std::endl;
276  DebugStop();
277  }
278 
279  mFileVersionInfo.clear();
280  mpStream->Read(mFileVersionInfo);
281 
282  uint64_t nObjects;
283  mpStream->Read(&nObjects);
284  mChunksVec.Resize(nObjects);
285 
286  int64_t objId;
287  int classId;
288  unsigned int objSize;
289  for (int64_t i = 0; i < nObjects; i++) {
290  mpStream->Read(&objId);
291  mpStream->Read(&classId);
292  mpStream->Read(&objSize);
293  mChunksVec[i] = new TPZChunkInTranslation(objId, classId, *mpStream, objSize, mFileVersionInfo);
294  }
295 
296  std::map<std::string, uint64_t> currentVersionInfo = mFileVersionInfo;
297  auto versionIt = std::find(mVersionHistory.begin(), mVersionHistory.end(), currentVersionInfo);
298  if (versionIt == mVersionHistory.end()) {
299  std::cerr << "This file cannot be read by this version of the program." << std::endl;
300  DebugStop();
301  }
302  versionIt++;
303 
304  while (versionIt != mVersionHistory.end()) {
305  std::map<std::string, uint64_t> nextVersion = *versionIt;
306  //@TODO parallelize
307  for (int64_t i = 0; i < nObjects; i++) {
308  auto chunk = mChunksVec[i];
309  chunk->mOldVersion = chunk->mNewVersion;
310  chunk->mOldStream = chunk->mNewStream;
311  chunk->mNewStream.clear();
312  }
313  //@TODO parallelize (it's already thread-safe)
314  for (int64_t i = 0; i < nObjects; i++) {
315  TPZAutoPointer<TPZChunkInTranslation> chunk = mChunksVec[i];
316  int classId = chunk->GetClassId();
317  if (classId != -1) { // this class still exists in this version
318  chunk->mNewVersion = nextVersion;
319  TPZChunkTranslator *translator = TPZSavable::ClassIdMap().at(classId)->GetTranslator();
320  if (translator) {
321  translator->UpdateStream(*chunk, nextVersion);
322  } else {
323  chunk->mNewStream = chunk->mOldStream;
324  }
325  }
326  }
327  currentVersionInfo = nextVersion;
328  nObjects = mChunksVec.size();
329  versionIt++;
330  }
331  // allocate
332  mObjVec.Resize(mChunksVec.size());
333  //@TODO parallelize (it's already thread-safe)
334  for (unsigned int i = 0; i < mObjVec.size(); ++i) {
335  int classId = mChunksVec[i]->GetClassId();
336  if (classId != -1) {
337  mObjVec[i].ResetReadStatus();
338  mObjVec[i].SetInstance(TPZSavable::CreateInstance(classId));
339  }
340  }
341 
342  //@TODO parallelize (with a semaphore to read each chunk)
343  for (unsigned int i = 0; i < mObjVec.size(); ++i) {
344  int classId = mChunksVec[i]->GetClassId();
345  if (classId != -1 && !mObjVec[i].IsAlreadyRead()) {
346  mObjVec[i].SetRead();
347  mObjVec[i].GetPointerToMyObj()->Read(mChunksVec[i]->mNewStream, NULL);
348 #ifdef PZDEBUG
349  if (mChunksVec[i]->mNewStream.Size() != 0) {
350  DebugStop();
351  }
352 #endif
353  }
354  }
355 
356  unsigned int nMainObjects;
357  mpStream->Read(&nMainObjects);
358  mMainObjIds.resize(nMainObjects);
359  for (unsigned int i = 0; i < nMainObjects; ++i) {
360  mpStream->Read(&mMainObjIds[i]);
361  }
362  mpStream->CloseRead();
363 
364  mNextMainObjIndex = 0;
365  return nMainObjects;
366 }
367 
369  auto nChunks = mChunksVec.size();
370  mChunksVec.resize(nChunks + 1);
371  return nChunks;
372 }
373 
375  mChunksVec[objId] = chunk;
376 }
377 
378 
380  auto nObjects = mObjVec.size();
381  mObjVec.Resize(nObjects + 1);
382  return &mObjVec[nObjects];
383 }
384 
386  TPZSavable *obj = GetInstance(mMainObjIds[mNextMainObjIndex++]);
387  if (mNextMainObjIndex == mMainObjIds.size()) {
388  CloseRead();
389  }
390  return obj;
391 }
392 
394  mObjVec[cId].SetInstance(obj);
395 }
396 
398  if (objId != -1) {
399  if (!mObjVec[objId].IsAlreadyRead()) {
400  mObjVec[objId].SetRead();
401  mObjVec[objId].GetPointerToMyObj()->Read(mChunksVec[objId]->mNewStream, NULL);
402  if (mChunksVec[objId]->mNewStream.Size() != 0) {
403  DebugStop();
404  }
405  }
406  return mObjVec[objId].GetPointerToMyObj();
407  }
408  return NULL;
409 }
410 
412  int64_t objId;
413  stream->Read(&objId);
414  return GetInstance(objId);
415 }
416 
418  TPZAutoPointer<TPZSavable> autoPointer;
419  if (objId != -1) {
420  if (!mObjVec[objId].IsAlreadyRead()) {
421  mObjVec[objId].SetRead();
422  mObjVec[objId].GetPointerToMyObj()->Read(mChunksVec[objId]->mNewStream, NULL);
423  if (mChunksVec[objId]->mNewStream.Size() != 0) {
424  DebugStop();
425  }
426  }
427  return mObjVec[objId].GetAutoPointerToMyObj();
428  }
429  return autoPointer;
430 }
431 
432 std::shared_ptr<TPZSavable> TPZPersistenceManager::GetSharedPointer(const int64_t &objId) {
433  if (objId != -1) {
434  if (!mObjVec[objId].IsAlreadyRead()) {
435  mObjVec[objId].SetRead();
436  mObjVec[objId].GetPointerToMyObj()->Read(mChunksVec[objId]->mNewStream, NULL);
437  if (mChunksVec[objId]->mNewStream.Size() != 0) {
438  DebugStop();
439  }
440  }
441  return mObjVec[objId].GetSharedPtrToMyObj();
442  }
443  std::shared_ptr<TPZSavable> sharedPtr;
444  return sharedPtr;
445 }
446 
448  int64_t objId;
449  stream->Read(&objId);
450  return GetAutoPointer(objId);
451 }
452 
453 std::shared_ptr<TPZSavable> TPZPersistenceManager::GetSharedPointer(TPZStream *stream) {
454  int64_t objId;
455  stream->Read(&objId);
456  return GetSharedPointer(objId);
457 }
458 
460  mMainObjIds.clear();
461  mChunksVec.clear();
462  mObjVec.clear();
463  mNextMainObjIndex = 0;
464 }
static std::list< std::map< std::string, uint64_t > > mVersionHistory
Class for creating a bidirectional circular buffer.
static std::map< const TPZSavable *, int64_t > mObjMap
virtual void Read(int *p, int howMany=1)
static TPZVec< const TPZSavable * > mPointersToSave
static void OpenWrite(const std::string &fileName, streamType=binary)
Contains declaration of the TPZSavable class which defines the interface to save and restore objects ...
static void TranslateNextPointer(TPZChunkInTranslation &chunk, const std::map< std::string, uint64_t > &toVersion)
static TPZSavable * ReadFromFile()
virtual void Write(const int *p, int howMany=1)
static int64_t NewChunkInTranslation()
static unsigned int OpenRead(const std::string &fileName, streamType=binary)
Templated vector implementation.
Defines PZError.
static TPZRestoredInstance * NewRestoredInstance()
virtual void Read(TPZStream &buf, void *context)
read objects from the stream
Definition: TPZSavable.cpp:61
static int64_t mNextPointerToSave
static TPZSavable * GetInstance(const int64_t &objId)
static void SetChunk(const int64_t &objId, TPZAutoPointer< TPZChunkInTranslation > chunk)
static void AddInstanceToVec(TPZSavable *, const int &id)
static TPZVec< TPZAutoPointer< TPZChunkInTranslation > > mChunksVec
virtual void UpdateStream(TPZChunkInTranslation &chunk, const std::map< std::string, uint64_t > &toVersion)
static TPZAutoPointer< TPZSavable > GetAutoPointer(const int64_t &objId)
TPZContBufferedStream mOldStream
virtual int ClassId() const =0
Define the class id associated with the class.
static TPZGeneralFStream * mpStream
static unsigned int mNextMainObjIndex
static TPZContBufferedStream mCurrentObjectStream
Implements reading from and writing to an ascii file. Persistency.
Definition: TPZFileStream.h:15
virtual void Write(const bool val)
Definition: TPZStream.cpp:8
#define DebugStop()
Returns a message to user put a breakpoint in.
Definition: pzerror.h:20
virtual std::pair< std::string, uint64_t > Version() const
Definition: TPZSavable.cpp:39
static void RegisterClassId(int classid, TPZRestore_t fun)
Definition: TPZSavable.cpp:76
static TPZSavable * CreateInstance(const int &classId)
Definition: TPZSavable.cpp:120
static std::shared_ptr< TPZSavable > GetSharedPointer(const int64_t &objId)
static std::map< int, TPZRestore_t > & ClassIdMap()
This static function guarantees that the gMap object is available when needed.
Definition: TPZSavable.h:77
static std::map< std::string, uint64_t > mFileVersionInfo
static TPZVec< int64_t > mMainObjIds
static void WriteToFile(const TPZSavable *)
static std::pair< std::string, uint64_t > NeoPZVersion()
Definition: TPZSavable.cpp:43
static int64_t ScheduleToWrite(const TPZSavable *obj)
std::map< std::string, uint64_t > mNewVersion
static TPZContBufferedStream mObjectsStream
static TPZVec< TPZRestoredInstance > mObjVec
Defines the interface for saving and reading data. Persistency.
Definition: TPZStream.h:50
virtual std::list< std::map< std::string, uint64_t > > VersionHistory() const
Definition: TPZSavable.cpp:22
This class defines the interface to save and restore objects from TPZStream objects. Persistency.
Definition: TPZSavable.h:67
static std::set< TPZRestoreClassBase * > & RestoreClassSet()
This static function guarantees that the gMap object is available when needed.
Definition: TPZSavable.h:71
static void WritePointer(const TPZSavable *obj, TPZStream *stream)
#define PZError
Defines the output device to error messages and the DebugStop() function.
Definition: pzerror.h:15
static void TranslatePointers(TPZChunkInTranslation &chunk, const std::map< std::string, uint64_t > &toVersion)
TPZContBufferedStream mNewStream
virtual void Read(bool &val)
Definition: TPZStream.cpp:91
obj
Definition: test.py:225