]> git.treefish.org Git - phys/latlib.git/blob - configcache.cpp
1b227578bea85c73835bffce7c343674340d109c
[phys/latlib.git] / configcache.cpp
1 #include "configcache.h"
2
3 #include <stdlib.h>
4 #include <iostream>
5 #include <time.h>
6 #include <dirent.h>
7
8 configcache::configcache(const string& cacheid, const int& nequi, const int& nskip, const string& datadir, char **configmem, const int& configMemSize, const int& cachemode,
9                          writeout *out_a){
10   out = out_a;
11
12   NEQUI = nequi;
13   NSKIP = nskip;
14   DATADIR = datadir;
15   CACHEID = cacheid;
16
17   configMem = (char*)malloc(configMemSize);
18   tmpConfig = (char*)malloc(configMemSize);
19
20   *configmem = configMem;
21   configSize = configMemSize;
22
23   outBuffer = NULL;
24   inBuffer = NULL;
25
26   MODE = cachemode;
27
28   refetchDataFiles = false;
29 }
30
31 string configcache::getFileId(const bool& shortid)
32 {
33   stringstream fileid;
34
35   if(!shortid) fileid << CACHEID << "_" << NEQUI << "_" << NSKIP;
36   for(int ipara=0; ipara<Paras.size(); ipara++)
37     fileid << "_" << Paras[ipara].id << Paras[ipara].val;
38
39   return fileid.str();
40 }
41
42 void configcache::fetchDataFiles()
43 {
44   struct dirent *de=NULL;
45   DIR *d=NULL;
46   static infiledesc filedesc;
47   
48   d=opendir(DATADIR.c_str());
49   if(d != NULL){
50     while(de = readdir(d)){
51       string filename = de->d_name;
52       if(isValidInFile(filename, &filedesc)) 
53         {
54           inFiles.push_back(filedesc);
55         }
56     }
57   }
58 }
59
60 bool configcache::isValidInFile(const string& infile, infiledesc *filedesc)
61 {
62   char *inchar, *inParts;
63   string truncIn, truncOut;
64
65   filedesc->filename = infile;
66   filedesc->doVirtualEquilibration = false;
67
68   if( infile.size() < 4 ) return false;
69
70   if( infile.substr(infile.size()-4) == ".dat" )
71     filedesc->extended = false;
72   else if( infile.substr(infile.size()-4) == "edat" )
73     filedesc->extended = true;
74   else
75     return false;
76
77   inchar = new char [infile.size()+1];
78   strcpy (inchar, infile.c_str());
79   
80   inParts = strtok( inchar, "_" );
81   for(int iPart=0; inParts!=NULL; iPart++)
82     {
83       if( iPart>3 ) { truncIn += "_"; truncIn += inParts; }
84
85       switch(iPart)
86         {
87         case 1: if(inParts != CACHEID) return false; break;
88         case 2: 
89           if (atoi(inParts) > NEQUI) 
90             return false; 
91           else if (atoi(inParts) < NEQUI)
92             filedesc->doVirtualEquilibration = true;
93           filedesc->nequi = atoi(inParts);
94           break;
95         case 3: 
96           if(atoi(inParts) != NSKIP) 
97             return false;
98           filedesc->nskip = atoi(inParts);
99           break;
100         }
101       inParts = strtok( NULL, "_");
102     }
103   truncIn = truncIn.substr(0, truncIn.size()-4);
104
105   delete[] inchar;
106
107   if( truncIn.find( getFileId(true) + "_" ) == string::npos ) return false;
108
109   return true;
110 }
111
112 bool configcache::openInFile() {
113   while( (!inFile.is_open()) && inFiles.size() > 0 )
114     {
115       if(out) *out->log << "CCACHE: Opening dat-file: " << inFiles.back().filename << endl << flush;
116
117       openFileDesc = inFiles.back();
118       inFile.open( (DATADIR + "/" + inFiles.back().filename).c_str(), std::ios::binary );
119       inFiles.pop_back();
120
121       if( !inFile.is_open() ) continue;
122
123       inBuffer = new boost::iostreams::filtering_istreambuf;
124       inBuffer->push( boost::iostreams::bzip2_decompressor() );
125       inBuffer->push(inFile);
126
127       return true;
128     }
129
130   return false;
131 }
132
133 void configcache::readHeader()
134 {
135   int headersize;
136   
137   if( readDataToMem((char*)&headersize, sizeof(int)) == sizeof(int) && inFile.is_open() )
138     {
139       if( headerData != NULL ) delete headerData;
140
141       headerData = new char(headersize);
142       
143       if( readDataToMem(headerData, headersize) == headersize && inFile.is_open() ) {
144         if(out) *out->log << "CCACHE: Read header information." << endl << flush;
145       }
146       else {
147         if(out) *out->log << "CCACHE: Could not read header! Closing dat-file: " << openFileDesc.filename << endl << flush;
148         inFile.close();
149       }
150     }
151   else {
152     if(out) *out->log << "CCACHE: Could not read header size! Closing dat-file: " << openFileDesc.filename << endl << flush;
153     inFile.close();
154   }
155 }
156
157 void *configcache::getHeader() {
158   return headerData;
159 }
160
161 bool configcache::readConfig()
162 {
163   if(DATADIR == "" || MODE == CACHE_MODE_DISABLED) return false;
164
165   if(refetchDataFiles){
166     refetchDataFiles = false;
167     fetchDataFiles();
168   }
169
170   while(true)
171     {
172       if( (!inFile.is_open()) && inFiles.size() == 0 ) return false;
173
174       /* read header information */
175       if ( openInFile() && openFileDesc.extended )
176         readHeader();
177
178       if( inFile.is_open() ) 
179         {
180           if (openFileDesc.doVirtualEquilibration) {
181             if(out) *out->log << "CCACHE: Trying virtual equilibration." << endl << flush;
182             openFileDesc.doVirtualEquilibration = false;
183             for (int iskip=0; iskip < (NEQUI-openFileDesc.nequi)/openFileDesc.nskip; iskip++) {
184               if( readDataToMem(tmpConfig, configSize) != configSize || ! inFile.is_open() )
185                 break;
186             }
187           }
188
189           if( readDataToMem(tmpConfig, configSize) == configSize && inFile.is_open() )
190             {
191               memcpy(configMem, tmpConfig, configSize);
192               return true;
193             }
194           else {
195             if(out) *out->log << "CCACHE: Could not read configuration. Closing dat-file: " << openFileDesc.filename << endl << flush;
196             inFile.close();
197           }
198         }
199     }
200 }
201
202 void configcache::openOutFile()
203 {
204   time_t secstamp = time(NULL);
205
206   outFileName.str("");
207   outFileName << DATADIR << "/" << secstamp << "_" << getFileId() << "_.edat.tmp";    
208   outFile.open( outFileName.str().c_str(), std::ios::binary );
209
210   outBuffer = new boost::iostreams::filtering_ostreambuf;
211   outBuffer->push(boost::iostreams::bzip2_compressor());
212   outBuffer->push(outFile);
213 }
214
215 void configcache::writeHeader(char *header, const int& size) {
216   if( DATADIR == "" || MODE < 2 ) return;
217
218   if(!outFile.is_open()) {
219     openOutFile();
220     boost::iostreams::write(*outBuffer, header, size);
221   }
222   else
223     if(out) *out->log << "CCACHE: Not writing header because outfile is already open!" << endl << flush;
224 }
225
226 void configcache::writeConfig()
227 {
228   if( DATADIR == "" || MODE < 2 ) return;
229
230   if(!outFile.is_open()){
231     int zeroheader=0;
232     openOutFile();
233     boost::iostreams::write(*outBuffer, (char*)&zeroheader, sizeof(int));
234   }
235
236   boost::iostreams::write(*outBuffer, configMem, configSize);
237 }
238
239 void configcache::addPara(const string& parid, const double& val){
240   parameter newPara;
241   newPara.id = parid;
242   newPara.val = val;
243   Paras.push_back(newPara);
244 }
245
246 int configcache::getParIndex(const string& parid){
247   for(int ipara=0; ipara<Paras.size(); ipara++)
248     if(Paras[ipara].id == parid) return ipara;
249 }
250
251 void configcache::setPara(const string& parid, const double& value){
252   Paras[getParIndex(parid)].val = value;
253   finishOutFile();
254   if(inBuffer != NULL) { delete inBuffer; inBuffer=NULL; } 
255   inFile.close();
256   inFiles.clear();
257
258   refetchDataFiles = true;
259 }
260
261 configcache::~configcache()
262 {
263   finishOutFile();
264   delete inBuffer;
265   inBuffer = NULL;
266 }
267
268 void configcache::finishOutFile()
269 {
270   if( outBuffer != NULL )
271     {
272       delete outBuffer;
273       outBuffer = NULL;
274     }
275
276   if( outFile.is_open() )
277     {
278       outFile.close();
279       rename( outFileName.str().c_str(), outFileName.str().substr(0, outFileName.str().size()-4).c_str() );
280     }
281 }
282
283 int configcache::readDataToMem(char *tmpData, long unsigned int dataSize)
284 {
285   int readturn = -1;
286
287   if ( dataSize == 0 ) return 0;
288
289   try { readturn = boost::iostreams::read(*inBuffer, tmpData, dataSize); }
290   catch(boost::iostreams::bzip2_error& error) { 
291     if(out) *out->log << "CCACHE: Caught bzip2 exception with error code: " << error.error() << endl << flush;
292     inFile.close();
293   } 
294   catch (std::exception const& ex) {
295     if(out) *out->log << "CCACHE: Caught exception: " << ex.what() << endl << flush;
296     inFile.close();
297   }
298   catch( ... ) {
299     if(out) *out->log << "CCACHE: Caught unknown exception while reading." << endl << flush;
300     inFile.close();
301   }
302
303   return readturn;
304 }