]> git.treefish.org Git - phys/latlib.git/blob - configcache.cpp
...
[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()-3) != "dat" ) return false;
71
72   inchar = new char [infile.size()+1];
73   strcpy (inchar, infile.c_str());
74   
75   inParts = strtok( inchar, "_" );
76   for(int iPart=0; inParts!=NULL; iPart++)
77     {
78       if( iPart>3 ) { truncIn += "_"; truncIn += inParts; }
79
80       switch(iPart)
81         {
82         case 1: if(inParts != CACHEID) return false; break;
83         case 2: 
84           if (atoi(inParts) > NEQUI) 
85             return false; 
86           else if (atoi(inParts) < NEQUI)
87             filedesc->doVirtualEquilibration = true;
88           filedesc->nequi = atoi(inParts);
89           break;
90         case 3: 
91           if(atoi(inParts) != NSKIP) 
92             return false;
93           filedesc->nskip = atoi(inParts);
94           break;
95         }
96       inParts = strtok( NULL, "_");
97     }
98   truncIn = truncIn.substr(0, truncIn.size()-4);
99
100   delete[] inchar;
101
102   if( truncIn.find( getFileId(true) + "_" ) == string::npos ) return false;
103
104   return true;
105 }
106
107 bool configcache::readConfig()
108 {
109   if(DATADIR == "" || MODE == CACHE_MODE_DISABLED) return false;
110
111   if(refetchDataFiles){
112     refetchDataFiles = false;
113     fetchDataFiles();
114   }
115
116   while(true)
117     {
118       if( (!inFile.is_open()) && inFiles.size() == 0 ) return false;
119
120       while( (!inFile.is_open()) && inFiles.size() > 0 )
121         {
122           if(out) *out->log << "CCACHE: Opening dat-file: " << inFiles.back().filename << endl << flush;
123
124           openFileDesc = inFiles.back();
125           inFile.open( (DATADIR + "/" + inFiles.back().filename).c_str(), std::ios::binary );
126           inFiles.pop_back();
127
128           if( !inFile.is_open() ) continue;
129
130           inBuffer = new boost::iostreams::filtering_istreambuf;
131           inBuffer->push( boost::iostreams::bzip2_decompressor() );
132           inBuffer->push(inFile);
133         }
134
135       if( inFile.is_open() ) 
136         {
137           if (openFileDesc.doVirtualEquilibration) {
138             if(out) *out->log << "CCACHE: Trying virtual equilibration." << endl << flush;
139             openFileDesc.doVirtualEquilibration = false;
140             for (int iskip=0; iskip < (NEQUI-openFileDesc.nequi)/openFileDesc.nskip; iskip++) {
141               if( readConfigToMem(tmpConfig) != configSize || ! inFile.is_open() )
142                 break;
143             }
144           }
145
146           if( readConfigToMem(tmpConfig) == configSize && inFile.is_open() )
147             {
148               memcpy(configMem, tmpConfig, configSize);
149               return true;
150             }
151           else {
152             if(out) *out->log << "CCACHE: Closing dat-file: " << openFileDesc.filename << endl << flush;
153             inFile.close();
154           }
155         }
156     }
157 }
158
159 void configcache::writeConfig()
160 {
161   if( DATADIR == "" || MODE < 2 ) return;
162
163   if(!outFile.is_open()){
164     time_t secstamp = time(NULL);
165
166     outFileName.str("");
167     outFileName << DATADIR << "/" << secstamp << "_" << getFileId() << "_.dat.tmp";    
168     outFile.open( outFileName.str().c_str(), std::ios::binary );
169
170     outBuffer = new boost::iostreams::filtering_ostreambuf;
171     outBuffer->push(boost::iostreams::bzip2_compressor());
172     outBuffer->push(outFile);
173   }
174
175   boost::iostreams::write(*outBuffer, configMem, configSize);
176 }
177
178 void configcache::addPara(const string& parid, const double& val){
179   parameter newPara;
180   newPara.id = parid;
181   newPara.val = val;
182   Paras.push_back(newPara);
183 }
184
185 int configcache::getParIndex(const string& parid){
186   for(int ipara=0; ipara<Paras.size(); ipara++)
187     if(Paras[ipara].id == parid) return ipara;
188 }
189
190 void configcache::setPara(const string& parid, const double& value){
191   Paras[getParIndex(parid)].val = value;
192   finishOutFile();
193   if(inBuffer != NULL) { delete inBuffer; inBuffer=NULL; } 
194   inFile.close();
195   inFiles.clear();
196
197   refetchDataFiles = true;
198 }
199
200 configcache::~configcache()
201 {
202   finishOutFile();
203   delete inBuffer;
204   inBuffer = NULL;
205 }
206
207 void configcache::finishOutFile()
208 {
209   if( outBuffer != NULL )
210     {
211       delete outBuffer;
212       outBuffer = NULL;
213     }
214
215   if( outFile.is_open() )
216     {
217       outFile.close();
218       rename( outFileName.str().c_str(), outFileName.str().substr(0, outFileName.str().size()-4).c_str() );
219     }
220 }
221
222 int configcache::readConfigToMem(char *tmpConfig)
223 {
224   int readturn = -1;
225
226   try { readturn = boost::iostreams::read(*inBuffer, tmpConfig, configSize); }
227   catch(boost::iostreams::bzip2_error& error) { 
228     if(out) *out->log << "CCACHE: Caught bzip2 exception with error code: " << error.error() << endl << flush;
229     inFile.close();
230   } 
231   catch (std::exception const& ex) {
232     if(out) *out->log << "CCACHE: Caught exception: " << ex.what() << endl << flush;
233     inFile.close();
234   }
235   catch( ... ) {
236     if(out) *out->log << "CCACHE: Caught unknown exception while reading." << endl << flush;
237     inFile.close();
238   }
239
240   return readturn;
241 }