Warning, /include/Geant4/tools/wroot/directory is written in an unsupported language. File is not indexed.
0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003
0004 #ifndef tools_wroot_directory
0005 #define tools_wroot_directory
0006
0007 #include "idir"
0008
0009 #include "date"
0010 #include "key"
0011 #include "ifile"
0012 #include "date"
0013 #include "buffer"
0014 #include "iobject"
0015
0016 #include "../strip"
0017 #include "../vmanip"
0018 #include "../forit"
0019
0020 #include <vector>
0021 #include <list>
0022
0023 namespace tools {
0024 namespace wroot {
0025
0026 class directory : public virtual idir {
0027 static uint32 class_version() {return 1;}
0028 public:
0029 static const std::string& s_class() {
0030 static const std::string s_v("tools::wroot::directory");
0031 return s_v;
0032 }
0033 public: //idir
0034 virtual ifile& file() {return m_file;}
0035 virtual seek seek_directory() const {return m_seek_directory;}
0036 virtual void append_object(iobject* a_object) {m_objs.push_back(a_object);} //take ownership of a_object
0037 public:
0038 directory(ifile& a_file)
0039 :m_file(a_file)
0040 ,m_parent(0)
0041 ,m_is_valid(false)
0042 ,m_date_C(0)
0043 ,m_date_M(0)
0044 ,m_nbytes_keys(0)
0045 ,m_nbytes_name(0)
0046 ,m_seek_directory(0)
0047 ,m_seek_parent(0)
0048 ,m_seek_keys(0)
0049 {
0050 #ifdef TOOLS_MEM
0051 mem::increment(s_class().c_str());
0052 #endif
0053 }
0054 directory(ifile& a_file,const std::string& a_name,const std::string& a_title)
0055 :m_file(a_file)
0056 ,m_parent(0)
0057 ,m_is_valid(false)
0058 ,m_name(a_name)
0059 ,m_title(a_title)
0060 ,m_nbytes_keys(0)
0061 ,m_nbytes_name(0)
0062 ,m_seek_directory(0)
0063 ,m_seek_parent(0)
0064 ,m_seek_keys(0)
0065 {
0066 #ifdef TOOLS_MEM
0067 mem::increment(s_class().c_str());
0068 #endif
0069 m_date_C = get_date();
0070 m_date_M = get_date();
0071
0072 if(m_name.empty()) {
0073 m_file.out() << "tools::wroot::directory::directory :"
0074 << " directory name cannot be \"\"."
0075 << std::endl;
0076 return; //FIXME : throw
0077 }
0078 if(m_name.find('/')!=std::string::npos) {
0079 m_file.out() << "tools::wroot::directory::directory :"
0080 << " directory name " << sout(m_name)
0081 << " cannot contain a slash."
0082 << std::endl;
0083 return; //FIXME : throw
0084 }
0085 if(m_title.empty()) m_title = m_name;
0086 m_is_valid = true;
0087 }
0088 directory(ifile& a_file,
0089 directory* a_parent, //assume a_parent not nul.
0090 const std::string& a_name,
0091 const std::string& a_title)
0092 :m_file(a_file)
0093 ,m_parent(a_parent)
0094 ,m_is_valid(false)
0095 ,m_name(a_name)
0096 ,m_title(a_title)
0097 ,m_nbytes_keys(0)
0098 ,m_nbytes_name(0)
0099 ,m_seek_directory(0)
0100 ,m_seek_parent(0)
0101 ,m_seek_keys(0)
0102 {
0103 #ifdef TOOLS_MEM
0104 mem::increment(s_class().c_str());
0105 #endif
0106 m_date_C = get_date();
0107 m_date_M = get_date();
0108
0109 if(m_name.empty()) {
0110 m_file.out() << "tools::wroot::directory::directory :"
0111 << " directory name cannot be \"\"."
0112 << std::endl;
0113 return; //FIXME : throw
0114 }
0115 if(m_name.find('/')!=std::string::npos) {
0116 m_file.out() << "tools::wroot::directory::directory :"
0117 << " directory name " << sout(m_name)
0118 << " cannot contain a slash."
0119 << std::endl;
0120 return; //FIXME : throw
0121 }
0122
0123 if(m_title.empty()) m_title = m_name;
0124
0125 if(m_parent->find_key(m_name)) {
0126 m_file.out() << "tools::wroot::directory::directory :"
0127 << " directory " << sout(m_name) << " exists already."
0128 << std::endl;
0129 return; //FIXME : throw
0130 }
0131
0132 m_seek_parent = m_parent->seek_directory();
0133 uint32 nbytes = record_size();
0134
0135 wroot::key* key = new wroot::key(m_file.out(),m_file,m_parent->seek_directory(),
0136 m_name,m_title,"TDirectory",nbytes); // It does a m_file.set_END().
0137 m_nbytes_name = key->key_length();
0138 m_seek_directory = key->seek_key(); //at EOF
0139 if(!m_seek_directory) {
0140 m_file.out() << "tools::wroot::directory::directory :"
0141 << " bad key."
0142 << std::endl;
0143 delete key;
0144 return; //FIXME : throw
0145 }
0146 {char* buffer = key->data_buffer();
0147 wbuf wb(m_file.out(),m_file.byte_swap(),key->eob(),buffer);
0148 if(!to_buffer(wb)) {
0149 m_file.out() << "tools::wroot::directory::directory :"
0150 << " directory name " << sout(m_name)
0151 << " cannot fill buffer."
0152 << std::endl;
0153 delete key;
0154 return; //FIXME : throw
0155 }}
0156 uint16 cycle = m_parent->append_key(key);
0157 key->set_cycle(cycle);
0158 if(!key->write_self(m_file)) {
0159 m_file.out() << "tools::wroot::directory::directory :"
0160 << " key.write_self() failed."
0161 << std::endl;
0162 return; //FIXME : throw
0163 }
0164 uint32 n;
0165 if(!key->write_file(m_file,n)) {
0166 m_file.out() << "tools::wroot::directory::directory :"
0167 << " directory name " << sout(m_name)
0168 << " cannot write key to file."
0169 << std::endl;
0170 return; //FIXME : throw
0171 }
0172
0173 m_is_valid = true;
0174 }
0175 virtual ~directory(){
0176 clear_dirs();
0177 clear_objs();
0178 clear_keys();
0179 #ifdef TOOLS_MEM
0180 mem::decrement(s_class().c_str());
0181 #endif
0182 }
0183 protected:
0184 directory(const directory& a_from)
0185 :idir(a_from)
0186 ,m_file(a_from.m_file)
0187 ,m_parent(0)
0188 ,m_is_valid(false){
0189 #ifdef TOOLS_MEM
0190 mem::increment(s_class().c_str());
0191 #endif
0192 }
0193 directory& operator=(const directory &){
0194 m_is_valid = false;
0195 return *this;
0196 }
0197 public:
0198 bool is_valid() const {return m_is_valid;}
0199 void set_seek_directory(seek a_seek) {m_seek_directory = a_seek;}
0200
0201 directory* mkdir(const std::string& a_name,const std::string& a_title = ""){
0202 // Create a sub-directory and return a pointer to the created directory.
0203 // Note that the directory name cannot contain slashes.
0204 if(a_name.empty()) {
0205 m_file.out() << "tools::wroot::directory::mkdir :"
0206 << " directory name cannot be \"\"."
0207 << std::endl;
0208 return 0;
0209 }
0210 if(a_name.find('/')!=std::string::npos) {
0211 m_file.out() << "tools::wroot::directory::mkdir :"
0212 << " " << sout(a_name)
0213 << " cannot contain a slash."
0214 << std::endl;
0215 return 0;
0216 }
0217 directory* dir = new directory(m_file,this,a_name,a_title.empty()?a_name:a_title);
0218 if(!dir->is_valid()) {
0219 m_file.out() << "tools::wroot::directory::mkdir :"
0220 << " directory badly created."
0221 << std::endl;
0222 delete dir;
0223 return 0;
0224 }
0225 m_dirs.push_back(dir);
0226 return dir;
0227 }
0228
0229 //uint32 nbytes_name() const {return m_nbytes_name;}
0230 void set_nbytes_name(uint32 a_n) {m_nbytes_name = a_n;}
0231
0232 uint32 record_size() const {
0233 uint32 nbytes = sizeof(short);
0234 nbytes += sizeof(date); //m_date_C.record_size();
0235 nbytes += sizeof(date); //m_date_M.record_size();
0236 nbytes += sizeof(m_nbytes_keys);
0237 nbytes += sizeof(m_nbytes_name);
0238 //ROOT version >= 40000:
0239 nbytes += sizeof(seek);
0240 nbytes += sizeof(seek);
0241 nbytes += sizeof(seek);
0242 return nbytes;
0243 }
0244
0245 bool close() {
0246 if(!save()) return false;
0247 clear_dirs();
0248 clear_objs();
0249 clear_keys();
0250 return true;
0251 }
0252
0253 bool to_buffer(wbuf& a_wb){
0254 // Decode input buffer.
0255 // (Name, title) are stored in the (name, title) of the associated key.
0256 short version = class_version();
0257 version += big_file_version_tag(); //GB : enforce writing on seek (and not seek32).
0258 if(!a_wb.write(version)) return false;
0259 if(!a_wb.write(m_date_C)) return false;
0260 if(!a_wb.write(m_date_M)) return false;
0261 if(!a_wb.write(m_nbytes_keys)) return false;
0262 if(!a_wb.write(m_nbytes_name)) return false;
0263
0264 if(!a_wb.write(m_seek_directory)) return false;
0265 if(!a_wb.write(m_seek_parent)) return false;
0266 if(!a_wb.write(m_seek_keys)) return false;
0267
0268 if(m_file.verbose()) {
0269 m_file.out() << "tools::wroot::key::to_buffer :"
0270 << " nbytes keys : " << m_nbytes_keys
0271 << ", pos keys : " << m_seek_keys
0272 << std::endl;
0273 }
0274 return true;
0275 }
0276
0277 bool write(uint32& a_nbytes){
0278 // Write all objects in memory to disk.
0279 // Loop on all objects in memory (including subdirectories).
0280 // A new key is created in the m_keys linked list for each object.
0281 // For allowed options see TObject::Write().
0282 // The directory header info is rewritten on the directory header record
0283 a_nbytes = 0;
0284 if(m_file.verbose()) {
0285 m_file.out() << "tools::wroot::directory::write :"
0286 << " " << sout(m_name)
0287 << " : " << m_dirs.size()
0288 << " : " << m_objs.size()
0289 << " objects."
0290 << std::endl;
0291 }
0292
0293 uint32 nbytes = 0;
0294
0295 {tools_vforcit(directory*,m_dirs,it) {
0296 uint32 n;
0297 if(!(*it)->write(n)) return false;
0298 nbytes += n;
0299 }}
0300
0301 {tools_vforit(iobject*,m_objs,it) {
0302 uint32 n;
0303 if(!write_object(*(*it),n)) {
0304 m_file.out() << "tools::wroot::directory::write :"
0305 << " for directory " << sout(m_name)
0306 << ", write_object " << sout((*it)->name())
0307 << " failed."
0308 << std::endl;
0309 return false;
0310 }
0311 nbytes += n;
0312 }}
0313
0314 if(!save_self()) {
0315 m_file.out() << "tools::wroot::directory::write :"
0316 << " for directory " << sout(m_name)
0317 << ", save_self failed."
0318 << std::endl;
0319 return false; //it will write keys of objects.
0320 }
0321
0322 a_nbytes = nbytes;
0323 return true;
0324 }
0325
0326 void clear_dirs() {safe_clear<directory>(m_dirs);}
0327 void clear_objs() {safe_clear<iobject>(m_objs);}
0328
0329 const std::list<key*>& keys() const {return m_keys;}
0330 //std::list<key*>& keys() {return m_keys;}
0331
0332 protected:
0333 void clear_keys() {
0334 std::list<key*>::iterator it;
0335 for(it=m_keys.begin();it!=m_keys.end();) {
0336 key* k = *it;
0337 it = m_keys.erase(it);
0338 delete k;
0339 }
0340 m_keys.clear();
0341 }
0342
0343 bool save(){
0344 if(!save_self()) return false;
0345 tools_vforit(directory*,m_dirs,it) {
0346 if(!(*it)->save()) return false;
0347 }
0348 return true;
0349 }
0350
0351 bool save_self() {
0352 // Save Directory keys and header :
0353 // If the directory has been modified (fModified set), write the keys
0354 // and the directory header.
0355 //if (fModified || aForce) {
0356 // if(!fFile.freeSegments().empty()) {
0357 // if(!writeKeys()) return false; // Write keys record.
0358 // if(!writeHeader()) return false; // Update directory record.
0359 // }
0360 //}
0361 if(!write_keys()) return false;
0362 if(!write_header()) return false;
0363 return true;
0364 }
0365
0366 key* find_key(const std::string& a_name) {
0367 if(m_file.verbose()) {
0368 m_file.out() << "tools::wroot::directory::find_key :"
0369 << " " << sout(a_name) << " ..."
0370 << std::endl;
0371 }
0372 tools_lforcit(key*,m_keys,it) {
0373 if((*it)->object_name()==a_name) return *it;
0374 }
0375
0376 return 0;
0377 }
0378 seek seek_keys() const {return m_seek_keys;}
0379
0380 uint16 append_key(key* a_key){ //take ownership of a_key
0381 tools_lforit(key*,m_keys,it) {
0382 if((*it)->object_name()==a_key->object_name()) {
0383 m_keys.insert(it,a_key); //a_key will be before *it.
0384 return ((*it)->cycle() + 1);
0385 }
0386 }
0387 // Not found :
0388 m_keys.push_back(a_key);
0389 return 1;
0390 }
0391
0392 bool write_keys(){
0393 // The list of keys (m_keys) is written as a single data record
0394 // Delete the old keys structure if it exists
0395
0396 //if(fSeekKeys) {
0397 // if(!fFile.makeFreeSegment
0398 // (fSeekKeys, fSeekKeys + fNbytesKeys -1)) return false;
0399 //}
0400
0401 // Write new keys record :
0402 uint32 nkeys = uint32(m_keys.size());
0403
0404 // Compute size of all keys
0405 uint32 nbytes = sizeof(nkeys);
0406
0407 {tools_lforit(key*,m_keys,it) {
0408 nbytes += (*it)->key_length();
0409 }}
0410
0411 key headerkey(m_file.out(),m_file,m_seek_directory,m_name,m_title,"TDirectory",nbytes); // m_file.set_END().
0412 if(!headerkey.seek_key()) return false;
0413
0414 {char* buffer = headerkey.data_buffer();
0415 wbuf wb(m_file.out(),m_file.byte_swap(),headerkey.eob(),buffer);
0416 if(!wb.write(nkeys)) return false;
0417 {tools_lforit(key*,m_keys,it) {
0418 if(!((*it)->to_buffer(wb,m_file.verbose()))) return false;
0419 }}}
0420
0421 m_seek_keys = headerkey.seek_key();
0422 m_nbytes_keys = headerkey.number_of_bytes();
0423
0424 if(m_file.verbose()) {
0425 m_file.out() << "tools::wroot::directory::write_keys :"
0426 << " write header key"
0427 << " " << sout(m_name)
0428 << " " << sout(m_title)
0429 << " (" << nkeys
0430 << ", " << nbytes
0431 << ", " << m_seek_keys
0432 << ", " << m_nbytes_keys
0433 << "):"
0434 << std::endl;
0435 }
0436
0437 headerkey.set_cycle(1);
0438 if(!headerkey.write_self(m_file)) {
0439 m_file.out() << "tools::wroot::directory::write_keys :"
0440 << " key.write_self() failed."
0441 << std::endl;
0442 return false;
0443 }
0444
0445 uint32 n;
0446 return headerkey.write_file(m_file,n);
0447 }
0448
0449 bool write_header(){
0450 // Overwrite the Directory header record.
0451 uint32 nbytes = record_size();
0452 char* header = new char[nbytes];
0453 char* buffer = header;
0454 m_date_M = get_date();
0455 wbuf wb(m_file.out(),m_file.byte_swap(),header+nbytes,buffer);
0456 if(!to_buffer(wb)) {
0457 delete [] header;
0458 return false;
0459 }
0460 // do not overwrite the name/title part
0461 seek pointer = m_seek_directory + m_nbytes_name;
0462 //fModified = false;
0463 if(!m_file.set_pos(pointer)) {
0464 delete [] header;
0465 return false;
0466 }
0467 if(!m_file.write_buffer(header,nbytes)) {
0468 delete [] header;
0469 return false;
0470 }
0471 if(!m_file.synchronize()) {
0472 delete [] header;
0473 return false;
0474 }
0475 delete [] header;
0476 return true;
0477 }
0478
0479 bool write_object(iobject& a_obj,uint32& a_nbytes){
0480 buffer bref(m_file.out(),m_file.byte_swap(),256*128); //32768
0481 if(!a_obj.stream(bref)) {
0482 m_file.out() << "tools::wroot::directory::write_object :"
0483 << " cannot stream object of store class name "
0484 << " " << sout(a_obj.store_class_name()) << "."
0485 << std::endl;
0486 a_nbytes = 0;
0487 return false;
0488 }
0489
0490 std::string name = a_obj.name();
0491 strip(name);
0492
0493 //first create the key to get key_length();
0494
0495 wroot::key* key = new wroot::key(m_file.out(),m_file,m_seek_directory,
0496 name,
0497 a_obj.title(),a_obj.store_class_name(),
0498 bref.length()); // It does a m_file.set_END().
0499
0500 if(!key->seek_key()) {
0501 delete key;
0502 return false;
0503 }
0504
0505 if(!bref.displace_mapped(key->key_length())) { //done before compression.
0506 delete key;
0507 return false;
0508 }
0509
0510 char* kbuf = 0;
0511 uint32 klen = 0;
0512 bool kdelete = false;
0513 m_file.compress_buffer(bref,kbuf,klen,kdelete);
0514
0515 ::memcpy(key->data_buffer(),kbuf,klen);
0516 if(kdelete) delete [] kbuf;
0517
0518 {uint32 nkey = key->key_length()+klen;
0519 m_file.set_END(key->seek_key()+nkey);
0520 key->set_number_of_bytes(nkey);}
0521
0522 uint16 cycle = append_key(key);
0523 key->set_cycle(cycle);
0524
0525 if(!key->write_self(m_file)) {
0526 m_file.out() << "tools::wroot::directory::write_object :"
0527 << " key.write_self() failed."
0528 << std::endl;
0529 return false;
0530 }
0531
0532 //FIXME m_file.sumBuffer(key->object_size()); //uncompressed data size.
0533
0534 if(m_file.verbose()) {
0535 m_file.out() << "tools::wroot::directory::_write_buffer :"
0536 << " " << sout(a_obj.name()) << "."
0537 << std::endl;
0538 }
0539
0540 return key->write_file(m_file,a_nbytes);
0541 }
0542
0543 protected:
0544 ifile& m_file;
0545 directory* m_parent;
0546 bool m_is_valid;
0547 std::string m_name;
0548 std::string m_title;
0549 std::vector<directory*> m_dirs;
0550 std::vector<iobject*> m_objs;
0551 std::list<key*> m_keys;
0552 // Record (stored in file):
0553 date m_date_C; //Date and time when directory is created
0554 date m_date_M; //Date and time of last modification
0555 uint32 m_nbytes_keys; //Number of bytes for the keys
0556 uint32 m_nbytes_name; //Number of bytes in TNamed at creation time
0557 seek m_seek_directory; //Location of directory on file
0558 seek m_seek_parent; //Location of parent directory on file
0559 seek m_seek_keys; //Location of Keys record on file
0560 };
0561
0562 }}
0563
0564 #endif