Remove warnings
[anna.git] / example / dbos / workdir / main.cpp
1 // ANNA - Anna is Not Nothingness Anymore                                                         //
2 //                                                                                                //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo                         //
4 //                                                                                                //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite                           //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
7
8
9 #include <iostream>
10
11 #include <anna/core/core.hpp>
12 #include <anna/app/app.hpp>
13
14 #include <anna/io/Directory.hpp>
15 #include <anna/io/functions.hpp>
16
17 #include <anna/xml/Compiler.hpp>
18 #include <anna/xml/Node.hpp>
19
20 #include <anna/dbos/Repository.hpp>
21 #include <anna/dbos/AutoObject.hpp>
22
23 #include "filesystem/Directory.hpp"
24 #include "filesystem/File.hpp"
25
26 #include "storage/Directory.hpp"
27 #include "storage/File.hpp"
28
29 using namespace std;
30 using namespace workdir;
31
32 template <typename T> void message (const char* text, T* tt) throw () {
33    if (Logger::isActive (Logger::Debug) == false)
34       return;
35
36    cout << "   " << text << " (";
37    cout << anna::functions::asHexString (anna_ptrnumber_cast (tt)); 
38    cout << "): ";
39    
40    if (tt != NULL)
41       cout << tt->asString ();
42    else
43       cout << "<null>";
44    
45    cout << endl;
46 }
47
48 class WorkDirectory : public Application {
49 public:
50    struct Flags { enum _v { None = 0, Clear = 1 }; };
51    
52    WorkDirectory ();
53
54    xml::Node* asXML (xml::Node* parent) const throw ();
55    
56 private:
57    typedef vector <storage::File*> file_container;
58    typedef file_container::iterator file_iterator;
59    typedef file_container::reverse_iterator file_reverse_iterator;
60    
61    dbos::Repository a_repository;
62    filesystem::Directory* a_root;
63    file_container a_files;
64
65    void initialize () throw (RuntimeException); 
66    void run () throw (RuntimeException);
67    
68    void forward (filesystem::Directory*) throw (RuntimeException);
69    void instantiateOne (filesystem::Directory*) throw (RuntimeException);   
70    void fullCache (filesystem::Directory*, file_container&, const int flags) throw (RuntimeException);   
71    void reuseHoles (filesystem::Directory*, file_container&) throw (RuntimeException);
72    void destroyObjects (filesystem::Directory* dir, file_container&) throw (RuntimeException);
73    void clear (file_container&) throw ();
74    
75    static void load (filesystem::Directory* parent, const int maxLevel, const int level = 0) throw (RuntimeException);
76 };
77
78 using namespace std;
79
80 int main (int argc, const char** argv)
81 {
82    CommandLine& commandLine (CommandLine::instantiate ());
83    WorkDirectory storageNull;
84
85    try {
86       commandLine.initialize (argv, argc);
87       commandLine.verify ();
88
89       Logger::setLevel (Logger::Local6); 
90       Logger::initialize ("workdir", new TraceWriter ("file.trace", 4 * 1024 * 1024));
91  
92       storageNull.start ();
93    }
94    catch (Exception& ex) {
95       cout << ex.asString () << endl;
96    }
97    
98    return 0;
99 }
100
101 WorkDirectory::WorkDirectory () : 
102    Application ("workdir", "Dbos workdir", "1.0.0"),
103    a_repository ("workdir")
104 {
105    CommandLine& cl (CommandLine::instantiate ());
106       
107    cl.add ("dir", CommandLine::Argument::Mandatory, "Nombre del directorio a procesar");
108    cl.add ("l", CommandLine::Argument::Optional, "Numero maximo de niveles de profundidad");
109    cl.add ("trace", CommandLine::Argument::Optional, "Nivel de trazado");
110    cl.add ("s", CommandLine::Argument::Mandatory, "Cache size");
111 }
112
113 void WorkDirectory::initialize ()
114    throw (RuntimeException)
115 {
116 }
117
118 void WorkDirectory::run () 
119    throw (RuntimeException)
120 {
121    LOGMETHOD (TraceMethod tm ("WorkDirectory", "run", ANNA_FILE_LOCATION)); 
122
123    CommandLine& cl (CommandLine::instantiate ());  
124
125    const std::string& dir = cl.getValue ("dir");
126    const int maxLevel = cl.exists ("l") ? cl.getIntegerValue ("l"): -1; 
127
128    if (cl.exists ("trace") == true) 
129       Logger::setLevel (Logger::asLevel (cl.getValue ("trace")));
130
131    const int cacheSize = cl.getIntegerValue ("s");
132    
133    storage::Directory::setup (a_repository, cacheSize);
134    storage::File::setup (a_repository, cacheSize);
135    
136    a_root = new filesystem::Directory (dir);
137    
138    load (a_root, maxLevel);
139    
140    a_root->print ();
141    cout << endl;
142
143    forward (a_root);
144       
145    writeContext ("file.context");
146 }  
147
148 xml::Node* WorkDirectory::asXML (xml::Node* parent) const
149    throw ()
150 {
151    xml::Node* result = app::Application::asXML (parent);
152    a_repository.asXML (result);
153    return result;
154 }
155
156 void WorkDirectory::forward (filesystem::Directory* dir)
157    throw (RuntimeException)
158 {
159    cout << "forward: " << dir->getPath () << endl;
160    
161    for (filesystem::Directory::child_iterator ii = dir->child_begin (), maxii = dir->child_end (); ii != maxii; ii ++) {
162       dir = filesystem::Directory::down_cast (filesystem::Directory::child (ii));
163       
164       if (dir == NULL) 
165          continue;
166      
167       try { 
168          instantiateOne (dir);
169          fullCache (dir, a_files, Flags::Clear);
170          reuseHoles (dir, a_files);
171          destroyObjects (dir, a_files);
172          forward (dir);      
173       }
174       catch (RuntimeException& ex) {
175          ex.trace ();
176       }
177    }   
178 }
179
180 /*
181  * Crea una serie de instancia simultáneas sobre el mismo objeto para verificar que sólo lo carga 
182  * de verdad sea necesario.
183  */ 
184 void WorkDirectory::instantiateOne (filesystem::Directory* dir) 
185    throw (RuntimeException)
186 {
187    TraceMethod tm ("WorkDirectory", "instantiateOne", ANNA_FILE_LOCATION);
188    
189    cout << "WorkDirectory::instantiateOne: Instancia varias veces la misma instancia para verificar el reuso" << endl;
190    
191    storage::Directory* aux;
192
193    {
194       dbos::AutoObject <storage::Directory> root1;   
195       aux = root1 = storage::Directory::instantiate (dir);
196       message ("Root1", aux);
197       
198       dbos::AutoObject <storage::Directory> root2;   
199       aux = root2 = storage::Directory::instantiate (dir);
200       message ("Root2", aux);
201    }
202    
203    dbos::AutoObject <storage::Directory> root3;   
204    aux = root3 = storage::Directory::instantiate (dir);
205    message ("Root3", aux);
206
207    message ("StorageArea", storage::File::getStorageArea ());
208
209    cout << endl;
210 }
211
212 void WorkDirectory::fullCache (filesystem::Directory* dir, WorkDirectory::file_container& files, const int flags) 
213    throw (RuntimeException)
214 {
215    TraceMethod tm ("WorkDirectory", "fullCache", ANNA_FILE_LOCATION);
216    
217    cout << "WorkDirectory::fullCache: Llena la cache de objetos para verificar que crece tanto como sea necesario" << endl;
218
219    filesystem::File* file;
220    
221    int maxSize = storage::File::getMaxSize ();
222    
223    maxSize += rand () % maxSize;
224    
225    for (filesystem::Directory::child_iterator ii = dir->child_begin (), maxii = dir->child_end (); ii != maxii; ii ++) {
226       file = filesystem::File::down_cast (filesystem::Directory::child (ii));
227       
228       if (file != NULL) {
229          storage::File* storageFile = storage::File::instantiate (file);
230          message ("File", storageFile);
231          files.push_back (storageFile);
232          
233 //         if (files.size () >= maxSize)
234 //            break;
235       }
236    }
237      
238    message ("StorageArea (full)", storage::File::getStorageArea ());
239
240    if (flags & Flags::Clear)
241       clear (files);
242    
243    message ("StorageArea (empty)", storage::File::getStorageArea ());
244    
245    cout << endl;
246 }
247
248 void WorkDirectory::reuseHoles (filesystem::Directory* dir, WorkDirectory::file_container& files)
249    throw (RuntimeException)
250 {
251    TraceMethod tm ("WorkDirectory", "reuseHoles", ANNA_FILE_LOCATION);
252    
253    cout << "WorkDirectory::reuseHoles: Invoca dos veces a fullCache para verificar que el tamano se mantiene la segunda vez" << endl;   
254    fullCache (dir, files, Flags::Clear);
255    fullCache (dir, files, Flags::Clear);      
256    cout << endl;
257 }
258
259 void WorkDirectory::destroyObjects (filesystem::Directory* dir, WorkDirectory::file_container& files)
260    throw (RuntimeException)
261 {
262    TraceMethod tm ("WorkDirectory", "destroyObjects", ANNA_FILE_LOCATION);
263    
264    cout << "WorkDirectory::destroyObjects: Carga un directorio distinto, para verificar que destruye los objetos segun se dejan de utilizar" << endl;   
265    filesystem::File* file;
266    filesystem::Directory* other = NULL;
267    
268    for (filesystem::Directory::child_iterator ii = dir->child_begin (), maxii = dir->child_end (); ii != maxii && other == NULL; ii ++) 
269       other = filesystem::Directory::down_cast (filesystem::Directory::child (ii));    
270          
271    if (other == NULL) {
272       cout << dir->getPath () << ": No se puede realizar esta prueba" << endl << endl;
273       return;
274    }
275    
276    cout << "New Directory: " << other->getPath () << endl;   
277    dir = other;
278    
279    for (filesystem::Directory::child_iterator ii = dir->child_begin (), maxii = dir->child_end (); ii != maxii; ii ++) {
280       file = filesystem::File::down_cast (filesystem::Directory::child (ii));
281       
282       if (file != NULL) {
283          storage::File* storageFile = storage::File::instantiate (file);
284          message ("File", storageFile);
285          storage::File::release (storageFile);         
286       }
287    }
288    
289    message ("StorageArea", storage::File::getStorageArea ());
290    
291    cout << endl;
292 }
293
294
295 void WorkDirectory::clear (WorkDirectory::file_container& files)
296    throw ()
297 {
298    storage::File* file;
299    
300    /* Libera los objetos en distinto orden para empeorar el tratamiento huecos */
301
302    if ((anna::functions::millisecond () % 2) == 0) {
303       cout << "Clear directo" << endl;
304       for (file_iterator ii = files.begin (), maxii = files.end (); ii != maxii; ii ++) {
305          file = *ii;
306          storage::File::release (file);
307       }      
308    }
309    else {
310       cout << "Clear inverso" << endl;
311       for (file_reverse_iterator ii = files.rbegin (), maxii = files.rend (); ii != maxii; ii ++) {
312          file = *ii;
313          storage::File::release (file);
314       }            
315    }
316    
317    files.clear ();
318 }
319
320 /*static*/
321 void WorkDirectory::load (filesystem::Directory* parent, const int maxLevel, const int level) 
322    throw (RuntimeException)
323 {
324    if (level == maxLevel)
325       return;
326    
327    io::Directory directory;
328    string fullPath;
329    
330    directory.read (parent->getPath (), io::Directory::Mode::ShortPath);
331    
332    for (io::Directory::const_iterator ii = directory.begin (), maxii = directory.end (); ii != maxii; ii ++) { 
333       const std::string& name = io::Directory::data (ii);
334       
335       fullPath = filesystem::Abstract::calculePath (parent, name);
336       
337       if (io::functions::isADirectory (fullPath)) {
338          try {
339             filesystem::Directory* dd = new filesystem::Directory (parent, name);
340             load (dd, maxLevel, level + 1);
341          }
342          catch (RuntimeException& ex) {
343             ex.trace ();
344          }
345       }
346       else {
347          //Auto association to the parent: 
348          new filesystem::File (parent, name);         
349       }
350    }      
351 }