1 // ANNA - Anna is Not Nothingness Anymore
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
5 // http://redmine.teslayout.com/projects/anna-suite
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
11 // * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
17 // * Neither the name of the copyright holder nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 // Authors: eduardo.ramos.testillano@gmail.com
34 // cisco.tierra@gmail.com
39 #include <anna/core/core.hpp>
40 #include <anna/app/app.hpp>
42 #include <anna/io/Directory.hpp>
43 #include <anna/io/functions.hpp>
45 #include <anna/xml/Compiler.hpp>
46 #include <anna/xml/Node.hpp>
48 #include <anna/dbos/Repository.hpp>
49 #include <anna/dbos/AutoObject.hpp>
51 #include "filesystem/Directory.hpp"
52 #include "filesystem/File.hpp"
54 #include "storage/Directory.hpp"
55 #include "storage/File.hpp"
58 using namespace workdir;
60 template <typename T> void message (const char* text, T* tt) throw () {
61 if (Logger::isActive (Logger::Debug) == false)
64 cout << " " << text << " (";
65 cout << anna::functions::asHexString (anna_ptrnumber_cast (tt));
69 cout << tt->asString ();
76 class WorkDirectory : public Application {
78 struct Flags { enum _v { None = 0, Clear = 1 }; };
82 xml::Node* asXML (xml::Node* parent) const throw ();
85 typedef vector <storage::File*> file_container;
86 typedef file_container::iterator file_iterator;
87 typedef file_container::reverse_iterator file_reverse_iterator;
89 dbos::Repository a_repository;
90 filesystem::Directory* a_root;
91 file_container a_files;
93 void initialize () throw (RuntimeException);
94 void run () throw (RuntimeException);
96 void forward (filesystem::Directory*) throw (RuntimeException);
97 void instantiateOne (filesystem::Directory*) throw (RuntimeException);
98 void fullCache (filesystem::Directory*, file_container&, const int flags) throw (RuntimeException);
99 void reuseHoles (filesystem::Directory*, file_container&) throw (RuntimeException);
100 void destroyObjects (filesystem::Directory* dir, file_container&) throw (RuntimeException);
101 void clear (file_container&) throw ();
103 static void load (filesystem::Directory* parent, const int maxLevel, const int level = 0) throw (RuntimeException);
108 int main (int argc, const char** argv)
110 CommandLine& commandLine (CommandLine::instantiate ());
111 WorkDirectory storageNull;
114 commandLine.initialize (argv, argc);
115 commandLine.verify ();
117 Logger::setLevel (Logger::Local6);
118 Logger::initialize ("workdir", new TraceWriter ("file.trace", 4 * 1024 * 1024));
120 storageNull.start ();
122 catch (Exception& ex) {
123 cout << ex.asString () << endl;
129 WorkDirectory::WorkDirectory () :
130 Application ("workdir", "Dbos workdir", "1.0.0"),
131 a_repository ("workdir")
133 CommandLine& cl (CommandLine::instantiate ());
135 cl.add ("dir", CommandLine::Argument::Mandatory, "Nombre del directorio a procesar");
136 cl.add ("l", CommandLine::Argument::Optional, "Nº máximo de niveles de profundidad");
137 cl.add ("trace", CommandLine::Argument::Optional, "Nivel de trazado");
138 cl.add ("s", CommandLine::Argument::Mandatory, "Cache size");
141 void WorkDirectory::initialize ()
142 throw (RuntimeException)
146 void WorkDirectory::run ()
147 throw (RuntimeException)
149 LOGMETHOD (TraceMethod tm ("WorkDirectory", "run", ANNA_FILE_LOCATION));
151 CommandLine& cl (CommandLine::instantiate ());
153 const std::string& dir = cl.getValue ("dir");
154 const int maxLevel = cl.exists ("l") ? cl.getIntegerValue ("l"): -1;
156 if (cl.exists ("trace") == true)
157 Logger::setLevel (Logger::asLevel (cl.getValue ("trace")));
159 const int cacheSize = cl.getIntegerValue ("s");
161 storage::Directory::setup (a_repository, cacheSize);
162 storage::File::setup (a_repository, cacheSize);
164 a_root = new filesystem::Directory (dir);
166 load (a_root, maxLevel);
173 writeContext ("file.context");
176 xml::Node* WorkDirectory::asXML (xml::Node* parent) const
179 xml::Node* result = app::Application::asXML (parent);
180 a_repository.asXML (result);
184 void WorkDirectory::forward (filesystem::Directory* dir)
185 throw (RuntimeException)
187 cout << "forward: " << dir->getPath () << endl;
189 for (filesystem::Directory::child_iterator ii = dir->child_begin (), maxii = dir->child_end (); ii != maxii; ii ++) {
190 dir = filesystem::Directory::down_cast (filesystem::Directory::child (ii));
196 instantiateOne (dir);
197 fullCache (dir, a_files, Flags::Clear);
198 reuseHoles (dir, a_files);
199 destroyObjects (dir, a_files);
202 catch (RuntimeException& ex) {
209 * Crea una serie de instancia simultáneas sobre el mismo objeto para verificar que sólo lo carga
210 * de verdad sea necesario.
212 void WorkDirectory::instantiateOne (filesystem::Directory* dir)
213 throw (RuntimeException)
215 TraceMethod tm ("WorkDirectory", "instantiateOne", ANNA_FILE_LOCATION);
217 cout << "WorkDirectory::instantiateOne: Instancia varias veces la misma instancia para verificar el reuso" << endl;
219 storage::Directory* aux;
222 dbos::AutoObject <storage::Directory> root1;
223 aux = root1 = storage::Directory::instantiate (dir);
224 message ("Root1", aux);
226 dbos::AutoObject <storage::Directory> root2;
227 aux = root2 = storage::Directory::instantiate (dir);
228 message ("Root2", aux);
231 dbos::AutoObject <storage::Directory> root3;
232 aux = root3 = storage::Directory::instantiate (dir);
233 message ("Root3", aux);
235 message ("StorageArea", storage::File::getStorageArea ());
240 void WorkDirectory::fullCache (filesystem::Directory* dir, WorkDirectory::file_container& files, const int flags)
241 throw (RuntimeException)
243 TraceMethod tm ("WorkDirectory", "fullCache", ANNA_FILE_LOCATION);
245 cout << "WorkDirectory::fullCache: Llena la cache de objetos para verificar que crece tanto como sea necesario" << endl;
247 filesystem::File* file;
249 int maxSize = storage::File::getMaxSize ();
251 maxSize += rand () % maxSize;
253 for (filesystem::Directory::child_iterator ii = dir->child_begin (), maxii = dir->child_end (); ii != maxii; ii ++) {
254 file = filesystem::File::down_cast (filesystem::Directory::child (ii));
257 storage::File* storageFile = storage::File::instantiate (file);
258 message ("File", storageFile);
259 files.push_back (storageFile);
261 // if (files.size () >= maxSize)
266 message ("StorageArea (full)", storage::File::getStorageArea ());
268 if (flags & Flags::Clear)
271 message ("StorageArea (empty)", storage::File::getStorageArea ());
276 void WorkDirectory::reuseHoles (filesystem::Directory* dir, WorkDirectory::file_container& files)
277 throw (RuntimeException)
279 TraceMethod tm ("WorkDirectory", "reuseHoles", ANNA_FILE_LOCATION);
281 cout << "WorkDirectory::reuseHoles: Invoca dos veces a fullCache para verificar que el tamaño se mantiene la 2ª vez" << endl;
282 fullCache (dir, files, Flags::Clear);
283 fullCache (dir, files, Flags::Clear);
287 void WorkDirectory::destroyObjects (filesystem::Directory* dir, WorkDirectory::file_container& files)
288 throw (RuntimeException)
290 TraceMethod tm ("WorkDirectory", "destroyObjects", ANNA_FILE_LOCATION);
292 cout << "WorkDirectory::destroyObjects: Carga un directorio distinto, para verificar que destruye los objetos según se dejan de utilizar" << endl;
293 filesystem::File* file;
294 filesystem::Directory* other = NULL;
296 for (filesystem::Directory::child_iterator ii = dir->child_begin (), maxii = dir->child_end (); ii != maxii && other == NULL; ii ++)
297 other = filesystem::Directory::down_cast (filesystem::Directory::child (ii));
300 cout << dir->getPath () << ": No se puede realizar esta prueba" << endl << endl;
304 cout << "New Directory: " << other->getPath () << endl;
307 for (filesystem::Directory::child_iterator ii = dir->child_begin (), maxii = dir->child_end (); ii != maxii; ii ++) {
308 file = filesystem::File::down_cast (filesystem::Directory::child (ii));
311 storage::File* storageFile = storage::File::instantiate (file);
312 message ("File", storageFile);
313 storage::File::release (storageFile);
317 message ("StorageArea", storage::File::getStorageArea ());
323 void WorkDirectory::clear (WorkDirectory::file_container& files)
328 /* Libera los objetos en distinto orden para empeorar el tratamiento huecos */
330 if ((anna::functions::millisecond () % 2) == 0) {
331 cout << "Clear directo" << endl;
332 for (file_iterator ii = files.begin (), maxii = files.end (); ii != maxii; ii ++) {
334 storage::File::release (file);
338 cout << "Clear inverso" << endl;
339 for (file_reverse_iterator ii = files.rbegin (), maxii = files.rend (); ii != maxii; ii ++) {
341 storage::File::release (file);
349 void WorkDirectory::load (filesystem::Directory* parent, const int maxLevel, const int level)
350 throw (RuntimeException)
352 if (level == maxLevel)
355 io::Directory directory;
358 directory.read (parent->getPath (), io::Directory::Mode::ShortPath);
360 for (io::Directory::const_iterator ii = directory.begin (), maxii = directory.end (); ii != maxii; ii ++) {
361 const std::string& name = io::Directory::data (ii);
363 fullPath = filesystem::Abstract::calculePath (parent, name);
365 if (io::functions::isADirectory (fullPath)) {
367 filesystem::Directory* dd = new filesystem::Directory (parent, name);
368 load (dd, maxLevel, level + 1);
370 catch (RuntimeException& ex) {
375 // Se asociado al parent automáticamente.
376 filesystem::File* ff = new filesystem::File (parent, name);