diff options
author | harrisb <harrisb@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2013-01-27 19:28:50 +0000 |
---|---|---|
committer | harrisb <harrisb@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2013-01-27 19:28:50 +0000 |
commit | ace6321eaa7ac291095daa685dd14229e8b9314b (patch) | |
tree | 3ada426b029cf0473457e8ed26a8b25a31eb6d15 | |
parent | b33919c4055efb00b753da39e5c9878fdb7b334e (diff) | |
download | ATCD-ace6321eaa7ac291095daa685dd14229e8b9314b.tar.gz |
Sun Jan 27 18:57:35 UTC 2013 Byron Harris <harrisb@ociweb.com>
31 files changed, 1136 insertions, 396 deletions
diff --git a/TAO/OCI_RE_ChangeLog b/TAO/OCI_RE_ChangeLog index 542a24e976d..0d334690cc8 100644 --- a/TAO/OCI_RE_ChangeLog +++ b/TAO/OCI_RE_ChangeLog @@ -1,3 +1,67 @@ +Sun Jan 27 18:57:35 UTC 2013 Byron Harris <harrisb@ociweb.com> + + * tao/Storable_Base.h: + * tao/Storable_Base.inl: + * tao/Storable_Base.cpp: + * tao/Storable_Factory.h: + * tao/Storable_File_Guard.h: + * tao/Storable_File_Guard.cpp: + * tao/Storable_FlatFileStream.h: + * tao/Storable_FlatFileStream.cpp: + + Added exceptions to throw when read and write + failures occur. + Added support to backup persistent files + and restoring when an exception is encountered + when trying to read from the file. + + * tests/Storable/Savable.h: + * tests/Storable/Savable.cpp: + * tests/Storable/data_files: + * tests/Storable/data_files/bad_binary.dat: + * tests/Storable/data_files/bad_int.dat: + * tests/Storable/data_files/bad_string.dat: + * tests/Storable/data_files/bad_unsigned_int.dat: + * tests/Storable/data_files/good.dat: + * tests/Storable/run_test.pl: + * tests/Storable/test.cpp: + + Update to test that backup file will be + used if an exception is encountered. + Verify this works for reading of various + types of data. + + * orbsvcs/orbsvcs/Naming/Storable_Naming_Context.h: + * orbsvcs/orbsvcs/Naming/Storable_Naming_Context.cpp: + * orbsvcs/orbsvcs/Naming/Storable_Naming_Context_ReaderWriter.cpp: + * orbsvcs/orbsvcs/PortableGroup/PG_Group_List_Store.cpp: + * orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Storable.cpp: + + Removed streaming reading error handling and let + Storable_FlatFileStream operations throw + Storable_Read_Exceptions instead. This way Storable_File_Guard + can transparently try to use backup files if a read exception + is encountered during reading. + + * orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Server.cpp: + + Enable support for backup/restore of persistent files. + + * orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data: + * orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/GroupService: + * orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/GroupService/ObjectGroup_0: + * orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/GroupService/ObjectGroup_global: + * orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/NameService: + * orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/NameService/NameService: + * orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/NameService/NameService_0: + * orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/NameService/NameService_1: + * orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/NameService/NameService_2: + * orbsvcs/tests/FT_Naming/FaultTolerant/run_persistence_test.pl: + + Update persistence test to verify that backup files are + generated and will be used if a corrupt file is being + read. + Fri Jan 25 22:39:26 UTC 2013 Kevin Stanley <stanleyk@ociweb.com> * orbsvcs/tests/FT_Naming/FaultTolerant/client.cpp: diff --git a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Server.cpp b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Server.cpp index fd3e2e9703d..fbaced68f6c 100644 --- a/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Server.cpp +++ b/TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Server.cpp @@ -608,6 +608,8 @@ TAO_FT_Naming_Server::parse_args (int argc, int u_opt_used = 0; int r_opt_used = 0; + int v_opt_used = 0; + // TODO: remove unsupported options with FT Naming Server while ((c = get_opts ()) != -1) switch (c) @@ -673,6 +675,7 @@ TAO_FT_Naming_Server::parse_args (int argc, case 'v': this->use_object_group_persistence_ = 1; this->object_group_dir_ = get_opts.opt_arg (); + v_opt_used = 1; break; #endif /* TAO_HAS_MINIMUM_POA == 0 */ @@ -733,6 +736,14 @@ TAO_FT_Naming_Server::parse_args (int argc, ACE_TEXT ("ERROR: Only one persistence option ") ACE_TEXT ("can be provided.\n\n")), -1); + + // If naming context or object group persistence is being used then + // enable backup/restore compability of persitent files. + if (u_opt_used || r_opt_used || v_opt_used) + { + TAO::Storable_Base::use_backup_default = true; + } + if (!role_defined) { // No role specified, so we will become a STANDALONE server this->replica_id_ = ACE_TEXT ("Standalone"); diff --git a/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context.cpp b/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context.cpp index 33454740341..51415d75293 100644 --- a/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context.cpp +++ b/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context.cpp @@ -261,11 +261,18 @@ TAO_Storable_Naming_Context::load_map (TAO::Storable_Base& storable) TAO_Storable_Naming_Context:: File_Open_Lock_and_Check::File_Open_Lock_and_Check ( TAO_Storable_Naming_Context * context, - const char * mode) + Method_Type method_type) : TAO::Storable_File_Guard (TAO_Storable_Naming_Context::redundant_), context_(context) { - init(mode); + try + { + this->init (method_type); + } + catch (const TAO::Storable_Read_Exception &) + { + throw CORBA::INTERNAL (); + } } TAO_Storable_Naming_Context:: @@ -345,6 +352,8 @@ File_Open_Lock_and_Check::create_stream (const char * mode) return context_->factory_->create_stream(file_name, ACE_TEXT_CHAR_TO_TCHAR(mode)); } +// Make shortcut to get to Method_Type enums +typedef TAO::Storable_File_Guard SFG; TAO_Storable_Naming_Context::TAO_Storable_Naming_Context ( CORBA::ORB_ptr orb, @@ -476,7 +485,7 @@ TAO_Storable_Naming_Context::new_context (void) { // Open the backing file - File_Open_Lock_and_Check flck(this, "r"); + File_Open_Lock_and_Check flck(this, SFG::ACCESSOR); // Check to make sure this object didn't have <destroy> method // invoked on it. @@ -499,12 +508,6 @@ TAO_Storable_Naming_Context::new_context (void) throw CORBA::INTERNAL(); // get the counter from disk rw.read_global(global); - if (!gfl_.get ()->good () && - gfl_.get ()->rdstate () != TAO::Storable_Base::eofbit) - { - gfl_.get ()->clear (); - throw CORBA::INTERNAL (); - } gcounter_ = global.counter(); // use it to generate a new name } @@ -542,7 +545,7 @@ TAO_Storable_Naming_Context::new_context (void) CORBA::NO_MEMORY ()); new_context->context_ = new_context->storable_context_; - File_Open_Lock_and_Check flck(new_context, "wc"); + File_Open_Lock_and_Check flck(new_context, SFG::CREATE_WITHOUT_FILE); new_context->Write(flck.peer()); return result._retn (); @@ -566,7 +569,7 @@ TAO_Storable_Naming_Context::rebind (const CosNaming::Name& n, CORBA::INTERNAL ()); // Open the backing file - File_Open_Lock_and_Check flck(this, name_len > 1 ? "r" : "rw"); + File_Open_Lock_and_Check flck(this, name_len > 1 ? SFG::ACCESSOR : SFG::MUTATOR); // Check to make sure this object didn't have <destroy> method // invoked on it. @@ -633,7 +636,7 @@ TAO_Storable_Naming_Context::bind_context (const CosNaming::Name &n, CORBA::INTERNAL ()); // Open the backing file - File_Open_Lock_and_Check flck(this, name_len > 1 ? "r" : "rw"); + File_Open_Lock_and_Check flck(this, name_len > 1 ? SFG::ACCESSOR : SFG::MUTATOR); // Check to make sure this object didn't have <destroy> method // invoked on it. @@ -693,7 +696,7 @@ TAO_Storable_Naming_Context::rebind_context (const CosNaming::Name &n, CORBA::INTERNAL ()); // Open the backing file - File_Open_Lock_and_Check flck(this, name_len > 1 ? "r" : "rw"); + File_Open_Lock_and_Check flck(this, name_len > 1 ? SFG::ACCESSOR : SFG::MUTATOR); // Check to make sure this object didn't have <destroy> method // invoked on it. @@ -752,7 +755,7 @@ TAO_Storable_Naming_Context::resolve (const CosNaming::Name& n) CORBA::INTERNAL ()); // Open the backing file - File_Open_Lock_and_Check flck(this, "r"); + File_Open_Lock_and_Check flck(this, SFG::ACCESSOR); // Check to make sure this object didn't have <destroy> method // invoked on it. @@ -841,7 +844,8 @@ TAO_Storable_Naming_Context::unbind (const CosNaming::Name& n) CORBA::INTERNAL ()); // Open the backing file - File_Open_Lock_and_Check flck(this, name_len > 1 ? "r" : "rw"); + File_Open_Lock_and_Check flck(this, name_len > 1 ? + SFG::ACCESSOR : SFG::MUTATOR); // Check to make sure this object didn't have <destroy> method // invoked on it. @@ -900,7 +904,8 @@ TAO_Storable_Naming_Context::bind_new_context (const CosNaming::Name& n) throw CORBA::OBJECT_NOT_EXIST (); // Open the backing file - File_Open_Lock_and_Check flck(this, name_len > 1 ? "r" : "rw"); + File_Open_Lock_and_Check flck(this, name_len > 1 ? + SFG::ACCESSOR : SFG::MUTATOR); // Check to make sure this object didn't have <destroy> method // invoked on it. @@ -969,7 +974,7 @@ TAO_Storable_Naming_Context::destroy (void) CORBA::INTERNAL ()); // Open the backing file - File_Open_Lock_and_Check flck(this, "rw"); + File_Open_Lock_and_Check flck(this, SFG::MUTATOR); // Check to make sure this object didn't have <destroy> method // invoked on it. @@ -1038,7 +1043,8 @@ TAO_Storable_Naming_Context::bind (const CosNaming::Name& n, CORBA::INTERNAL ()); // Open the backing file - File_Open_Lock_and_Check flck(this, name_len > 1 ? "r" : "rw"); + File_Open_Lock_and_Check flck(this, name_len > 1 ? + SFG::ACCESSOR : SFG::MUTATOR); // Check to make sure this object didn't have <destroy> method // invoked on it. @@ -1101,7 +1107,7 @@ TAO_Storable_Naming_Context::list (CORBA::ULong how_many, CORBA::INTERNAL ()); // Open the backing file - File_Open_Lock_and_Check flck(this, "r"); + File_Open_Lock_and_Check flck(this, SFG::ACCESSOR); // Check to make sure this object didn't have <destroy> method // invoked on it. @@ -1248,7 +1254,7 @@ CosNaming::NamingContext_ptr TAO_Storable_Naming_Context::recreate_all ( if (fl->exists ()) { // Load the map from disk - File_Open_Lock_and_Check flck (new_context, "r"); + File_Open_Lock_and_Check flck (new_context, SFG::CREATE_WITH_FILE); } else { @@ -1257,15 +1263,20 @@ CosNaming::NamingContext_ptr TAO_Storable_Naming_Context::recreate_all ( TAO_Storable_Bindings_Map (context_size,orb), CORBA::NO_MEMORY ()); new_context->context_ = new_context->storable_context_; - File_Open_Lock_and_Check flck (new_context, "wc"); + File_Open_Lock_and_Check flck (new_context, SFG::CREATE_WITHOUT_FILE); new_context->Write (flck.peer ()); } // build the global file name file_name += ACE_TEXT("_global"); - // Create the stream for the counter used to uniquely creat context names - gfl_.reset(pers_factory->create_stream (ACE_TEXT_ALWAYS_CHAR(file_name.c_str()), ACE_TEXT("crw"))); + // Create the stream for the counter used to uniquely create context names + // Pass false for use_backup since access to this file is not wrapped + // around a Storable_File_Guard derived class. + gfl_.reset(pers_factory-> + create_stream (ACE_TEXT_ALWAYS_CHAR(file_name.c_str()), + ACE_TEXT("crw"), + false)); if (gfl_->open() != 0) { delete gfl_.release(); @@ -1276,12 +1287,6 @@ CosNaming::NamingContext_ptr TAO_Storable_Naming_Context::recreate_all ( TAO_NS_Persistence_Global global; TAO_Storable_Naming_Context_ReaderWriter rw(*gfl_.get()); rw.read_global(global); - if (!gfl_.get ()->good () && - gfl_.get ()->rdstate () != TAO::Storable_Base::eofbit) - { - gfl_.get ()->clear (); - throw CORBA::INTERNAL (); - } gcounter_ = global.counter(); if(redundant_) gfl_->close(); diff --git a/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context.h b/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context.h index 50a4cc189b0..9d28d4d4c31 100644 --- a/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context.h +++ b/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context.h @@ -435,7 +435,7 @@ public: /// Constructor - we always need the object which we guard. File_Open_Lock_and_Check (TAO_Storable_Naming_Context * context, - const char * mode); + Method_Type method_type); ~File_Open_Lock_and_Check (); diff --git a/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context_ReaderWriter.cpp b/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context_ReaderWriter.cpp index c00934536f0..c21b331f6d9 100644 --- a/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context_ReaderWriter.cpp +++ b/TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context_ReaderWriter.cpp @@ -21,30 +21,27 @@ TAO_BEGIN_VERSIONED_NAMESPACE_DECL TAO_Storable_Naming_Context_ReaderWriter:: TAO_Storable_Naming_Context_ReaderWriter (TAO::Storable_Base & stream) - : stream_ (stream) + : stream_(stream) { } void -TAO_Storable_Naming_Context_ReaderWriter::write ( - TAO_Storable_Naming_Context & context) +TAO_Storable_Naming_Context_ReaderWriter::write (TAO_Storable_Naming_Context & context) { TAO_NS_Persistence_Header header; - header.size (static_cast<unsigned int> ( - context.storable_context_->current_size ())); - + header.size (static_cast<unsigned int> (context.storable_context_->current_size())); header.destroyed (context.destroyed_); - this->write_header (header); + this->write_header(header); if (0u == header.size ()) return; - ACE_Hash_Map_Iterator<TAO_Storable_ExtId,TAO_Storable_IntId, ACE_Null_Mutex> - it = context.storable_context_->map ().begin (); - ACE_Hash_Map_Iterator<TAO_Storable_ExtId,TAO_Storable_IntId,ACE_Null_Mutex> - itend = context.storable_context_->map ().end (); + ACE_Hash_Map_Iterator<TAO_Storable_ExtId,TAO_Storable_IntId, + ACE_Null_Mutex> it = context.storable_context_->map().begin(); + ACE_Hash_Map_Iterator<TAO_Storable_ExtId,TAO_Storable_IntId, + ACE_Null_Mutex> itend = context.storable_context_->map().end(); ACE_Hash_Map_Entry<TAO_Storable_ExtId,TAO_Storable_IntId> ent = *it; @@ -107,34 +104,32 @@ TAO_Storable_Naming_Context_ReaderWriter::write ( name.set ((*it).int_id_.ref_.in ()); // The non-context object IOR record.type (TAO_NS_Persistence_Record::OBJREF); } - record.ref (name); + record.ref(name); - const char *myid = (*it).ext_id_.id (); - ACE_CString id (myid); - record.id (id); + const char *myid = (*it).ext_id_.id(); + ACE_CString id(myid); + record.id(id); - const char *mykind = (*it).ext_id_.kind (); - ACE_CString kind (mykind); - record.kind (kind); + const char *mykind = (*it).ext_id_.kind(); + ACE_CString kind(mykind); + record.kind(kind); write_record (record); - it.advance (); + it.advance(); } context.write_occurred_ = 1; } int -TAO_Storable_Naming_Context_ReaderWriter::read ( - TAO_Storable_Naming_Context & context) +TAO_Storable_Naming_Context_ReaderWriter::read (TAO_Storable_Naming_Context & context) { // assume file already open for reading TAO_Storable_Bindings_Map *bindings_map; // create the new bindings map ACE_NEW_THROW_EX (bindings_map, - TAO_Storable_Bindings_Map (context.hash_table_size_, - context.orb_.in ()), + TAO_Storable_Bindings_Map (context.hash_table_size_, context.orb_.in()), CORBA::NO_MEMORY ()); // get the data for this bindings map from the file @@ -143,25 +138,15 @@ TAO_Storable_Naming_Context_ReaderWriter::read ( TAO_NS_Persistence_Record record; // we are only using the size from this header - this->read_header (header); - if (!stream_.good ()) - { - stream_.clear (); - throw CORBA::INTERNAL (); - } + this->read_header(header); // reset the destroyed flag - context.destroyed_ = header.destroyed (); + context.destroyed_ = header.destroyed(); // read in the data for the map - for (unsigned int i= 0u; i<header.size (); ++i) + for (unsigned int i= 0u; i<header.size(); ++i) { - this->read_record (record); - if (!stream_.good ()) - { - stream_.clear (); - throw CORBA::INTERNAL (); - } + this->read_record(record); if (TAO_NS_Persistence_Record::LOCAL_NCONTEXT == record.type ()) { @@ -183,8 +168,7 @@ TAO_Storable_Naming_Context_ReaderWriter::read ( bindings_map->bind ( record.id ().c_str (), record.kind ().c_str (), objref.in (), - ((TAO_NS_Persistence_Record::REMOTE_NCONTEXT - == record.type ()) + ((TAO_NS_Persistence_Record::REMOTE_NCONTEXT == record.type ()) ? CosNaming::ncontext // REMOTE_NCONTEXT : CosNaming::nobject )); // OBJREF } @@ -195,47 +179,43 @@ TAO_Storable_Naming_Context_ReaderWriter::read ( } void -TAO_Storable_Naming_Context_ReaderWriter::write_header ( - const TAO_NS_Persistence_Header & header) +TAO_Storable_Naming_Context_ReaderWriter::write_header (const TAO_NS_Persistence_Header & header) { - stream_.rewind (); - stream_ << header.size (); - stream_ << header.destroyed (); - stream_.flush (); + stream_.rewind(); + stream_ << header.size(); + stream_ << header.destroyed(); + stream_.flush(); } void -TAO_Storable_Naming_Context_ReaderWriter::read_header ( - TAO_NS_Persistence_Header & header) +TAO_Storable_Naming_Context_ReaderWriter::read_header (TAO_NS_Persistence_Header & header) { unsigned int size; int destroyed; - stream_.rewind (); + stream_.rewind(); stream_ >> size; - header.size (size); + header.size(size); stream_ >> destroyed; - header.destroyed (destroyed); + header.destroyed(destroyed); } void -TAO_Storable_Naming_Context_ReaderWriter::write_record ( - const TAO_NS_Persistence_Record & record) +TAO_Storable_Naming_Context_ReaderWriter::write_record (const TAO_NS_Persistence_Record & record) { - TAO_NS_Persistence_Record::Record_Type type = record.type (); + TAO_NS_Persistence_Record::Record_Type type = record.type(); stream_ << type; - stream_ << record.id (); - stream_ << record.kind (); - stream_ << record.ref (); + stream_ << record.id(); + stream_ << record.kind(); + stream_ << record.ref(); - stream_.flush (); + stream_.flush(); } void -TAO_Storable_Naming_Context_ReaderWriter::read_record ( - TAO_NS_Persistence_Record & record) +TAO_Storable_Naming_Context_ReaderWriter::read_record (TAO_NS_Persistence_Record & record) { int temp_type_in; stream_ >> temp_type_in; @@ -257,23 +237,33 @@ TAO_Storable_Naming_Context_ReaderWriter::read_record ( } void -TAO_Storable_Naming_Context_ReaderWriter::write_global ( - const TAO_NS_Persistence_Global & global) +TAO_Storable_Naming_Context_ReaderWriter::write_global (const TAO_NS_Persistence_Global & global) { - stream_.rewind (); - stream_ << global.counter (); - stream_.flush (); + stream_.rewind(); + stream_ << global.counter(); + stream_.flush(); } void -TAO_Storable_Naming_Context_ReaderWriter::read_global ( - TAO_NS_Persistence_Global & global) +TAO_Storable_Naming_Context_ReaderWriter::read_global (TAO_NS_Persistence_Global + & global) { unsigned int counter = 0; - stream_.rewind (); - stream_ >> counter; - global.counter (counter); + stream_.rewind(); + // We expect an exception to be thrown with EOF state if the file is empty. + try + { + stream_ >> counter; + } + catch (TAO::Storable_Read_Exception &ex) + { + if (ex.get_state() != TAO::Storable_Base::goodbit && + ex.get_state() != TAO::Storable_Base::eofbit) + throw CORBA::INTERNAL (); + } + + global.counter(counter); } diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_List_Store.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_List_Store.cpp index 9bfdebcffd0..97541e4c009 100644 --- a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_List_Store.cpp +++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_List_Store.cpp @@ -26,8 +26,8 @@ namespace TAO class PG_Group_List_Store_File_Guard : public TAO::Storable_File_Guard { public: - PG_Group_List_Store_File_Guard ( PG_Group_List_Store & list_store, - const char * mode); + PG_Group_List_Store_File_Guard (PG_Group_List_Store & list_store, + Method_Type method_type); ~PG_Group_List_Store_File_Guard (); @@ -52,11 +52,18 @@ private: } TAO::PG_Group_List_Store_File_Guard::PG_Group_List_Store_File_Guard ( - PG_Group_List_Store & list_store, const char * mode) + PG_Group_List_Store & list_store, Method_Type method_type) : TAO::Storable_File_Guard(true), list_store_(list_store) { - this->init(mode); + try + { + this->init (method_type); + } + catch (const TAO::Storable_Read_Exception &) + { + throw CORBA::INTERNAL (); + } } TAO::PG_Group_List_Store_File_Guard::~PG_Group_List_Store_File_Guard () @@ -114,6 +121,9 @@ TAO::PG_Group_List_Store_File_Guard::create_stream (const char * mode) typedef TAO::PG_Group_List_Store_File_Guard File_Guard; +// Make shortcut to get to Method_Type enums +typedef TAO::Storable_File_Guard SFG; + TAO::PG_Group_List_Store::PG_Group_List_Store ( Storable_Factory & storable_factory) : next_group_id_ (0) @@ -135,11 +145,11 @@ TAO::PG_Group_List_Store::PG_Group_List_Store ( if (stream_exists) { - File_Guard fg(*this, ACE_TEXT_ALWAYS_CHAR ("r")); + File_Guard fg(*this, SFG::CREATE_WITH_FILE); } else { - File_Guard fg(*this, ACE_TEXT_ALWAYS_CHAR ("wc")); + File_Guard fg(*this, SFG::CREATE_WITHOUT_FILE); this->write (fg.peer ()); } } @@ -151,7 +161,7 @@ TAO::PG_Group_List_Store::~PG_Group_List_Store () PortableGroup::ObjectGroupId TAO::PG_Group_List_Store::get_next_group_id () { - File_Guard fg(*this, "rw"); + File_Guard fg(*this, SFG::ACCESSOR); PortableGroup::ObjectGroupId next_id = this->next_group_id_; ++this->next_group_id_; this->write (fg.peer ()); @@ -161,7 +171,7 @@ TAO::PG_Group_List_Store::get_next_group_id () int TAO::PG_Group_List_Store::add (PortableGroup::ObjectGroupId id) { - File_Guard fg(*this, "rw"); + File_Guard fg(*this, SFG::MUTATOR); Group_Id_Const_Iterator it = std::find (this->group_ids_.begin (), this->group_ids_.end (), id); @@ -175,7 +185,7 @@ TAO::PG_Group_List_Store::add (PortableGroup::ObjectGroupId id) int TAO::PG_Group_List_Store::remove (PortableGroup::ObjectGroupId id) { - File_Guard fg(*this, "rw"); + File_Guard fg(*this, SFG::MUTATOR); Group_Id_Iterator it = std::find (this->group_ids_.begin (), this->group_ids_.end (), id); @@ -189,7 +199,7 @@ TAO::PG_Group_List_Store::remove (PortableGroup::ObjectGroupId id) TAO::PG_Group_List_Store::Group_Ids & TAO::PG_Group_List_Store::get_group_ids () { - File_Guard fg(*this, ACE_TEXT_ALWAYS_CHAR ("r")); + File_Guard fg(*this, SFG::ACCESSOR); return group_ids_; } @@ -199,19 +209,13 @@ TAO::PG_Group_List_Store::read (TAO::Storable_Base & stream) group_ids_.clear (); stream.rewind (); - if (!stream.good ()) - throw CORBA::INTERNAL (); unsigned int next_group_id; stream >> next_group_id; this->next_group_id_ = next_group_id; - if (!stream.good ()) - throw CORBA::INTERNAL (); int size; stream >> size; - if (!stream.good ()) - throw CORBA::INTERNAL (); // TODO: Look at adding streaming of unsigned long long // PortableGroup::ObjectGroupId group_id; @@ -219,8 +223,6 @@ TAO::PG_Group_List_Store::read (TAO::Storable_Base & stream) for (int i = 0; i < size; ++i) { stream >> group_id; - if (!stream.good ()) - throw CORBA::INTERNAL (); group_ids_.insert (group_id); } } diff --git a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Storable.cpp b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Storable.cpp index dc571b4ff25..7a457881ca4 100644 --- a/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Storable.cpp +++ b/TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Storable.cpp @@ -15,21 +15,11 @@ namespace { int size; stream >> size; - if (!stream.good ()) - { - stream.clear (); - throw CORBA::INTERNAL (); - } char *tmp = 0; ACE_NEW_THROW_EX (tmp, char [size], CORBA::NO_MEMORY ()); ACE_Auto_Basic_Array_Ptr<char> buf (tmp); stream.read (size, buf.get ()); - if (!stream.good ()) - { - stream.clear (); - throw CORBA::INTERNAL (); - } TAO_InputCDR cdr (buf.get (), size); cdr >> corba_data; @@ -49,7 +39,7 @@ namespace TAO public: Object_Group_File_Guard ( TAO::PG_Object_Group_Storable & object_group, - const char *mode); + Method_Type method_type); ~Object_Group_File_Guard (); @@ -81,11 +71,18 @@ namespace TAO TAO::Object_Group_File_Guard::Object_Group_File_Guard ( TAO::PG_Object_Group_Storable & object_group, - const char *mode) + Method_Type method_type) : TAO::Storable_File_Guard(true) , object_group_(object_group) { - this->init (mode); + try + { + this->init (method_type); + } + catch (const TAO::Storable_Read_Exception &) + { + throw CORBA::INTERNAL (); + } } TAO::Object_Group_File_Guard::~Object_Group_File_Guard () @@ -141,6 +138,9 @@ TAO::Object_Group_File_Guard::create_stream (const char * mode) return object_group_.create_stream (mode); } +// Make shortcut to get to Method_Type enums +typedef TAO::Storable_File_Guard SFG; + TAO::PG_Object_Group_Storable::PG_Object_Group_Storable ( CORBA::ORB_ptr orb, PortableGroup::FactoryRegistry_ptr factory_registry, @@ -180,11 +180,11 @@ TAO::PG_Object_Group_Storable::PG_Object_Group_Storable ( if (stream_exists) { - Object_Group_File_Guard fg (*this, ACE_TEXT_ALWAYS_CHAR ("r")); + Object_Group_File_Guard fg (*this, SFG::CREATE_WITH_FILE); } else { - Object_Group_File_Guard fg (*this, ACE_TEXT_ALWAYS_CHAR ("wc")); + Object_Group_File_Guard fg (*this, SFG::CREATE_WITHOUT_FILE); this->write (fg.peer ()); } } @@ -219,7 +219,7 @@ TAO::PG_Object_Group_Storable::PG_Object_Group_Storable ( if (stream_exists) { - Object_Group_File_Guard fg (*this, ACE_TEXT_ALWAYS_CHAR ("r")); + Object_Group_File_Guard fg (*this, SFG::ACCESSOR); } else { @@ -252,7 +252,7 @@ TAO::PG_Object_Group_Storable::set_destroyed (bool destroyed) const PortableGroup::Location & TAO::PG_Object_Group_Storable::get_primary_location (void) { - Object_Group_File_Guard fg (*this, ACE_TEXT_ALWAYS_CHAR ("r")); + Object_Group_File_Guard fg (*this, SFG::ACCESSOR); return TAO::PG_Object_Group::get_primary_location (); } @@ -262,7 +262,7 @@ TAO::PG_Object_Group_Storable::add_member ( const PortableGroup::Location & the_location, CORBA::Object_ptr member) { - Object_Group_File_Guard fg (*this, ACE_TEXT_ALWAYS_CHAR ("rw")); + Object_Group_File_Guard fg (*this, SFG::MUTATOR); PG_Object_Group::add_member (the_location, member); this->write (fg.peer ()); } @@ -272,7 +272,7 @@ TAO::PG_Object_Group_Storable::set_primary_member ( TAO_IOP::TAO_IOR_Property * prop, const PortableGroup::Location & the_location) { - Object_Group_File_Guard fg (*this, ACE_TEXT_ALWAYS_CHAR ("rw")); + Object_Group_File_Guard fg (*this, SFG::MUTATOR); int primary_member = PG_Object_Group::set_primary_member (prop, the_location); this->write (fg.peer ()); return primary_member; @@ -282,7 +282,7 @@ void TAO::PG_Object_Group_Storable::remove_member ( const PortableGroup::Location & the_location) { - Object_Group_File_Guard fg (*this, ACE_TEXT_ALWAYS_CHAR ("rw")); + Object_Group_File_Guard fg (*this, SFG::MUTATOR); PG_Object_Group::remove_member (the_location); this->write (fg.peer ()); } @@ -291,7 +291,7 @@ TAO::PG_Object_Group_Storable::remove_member ( PortableGroup::Locations * TAO::PG_Object_Group_Storable::locations_of_members (void) { - Object_Group_File_Guard fg (*this, ACE_TEXT_ALWAYS_CHAR ("r")); + Object_Group_File_Guard fg (*this, SFG::ACCESSOR); return PG_Object_Group::locations_of_members (); } @@ -301,7 +301,7 @@ TAO::PG_Object_Group_Storable::create_member ( const char * type_id, const PortableGroup::Criteria & the_criteria) { - Object_Group_File_Guard fg (*this, ACE_TEXT_ALWAYS_CHAR ("rw")); + Object_Group_File_Guard fg (*this, SFG::MUTATOR); PG_Object_Group::create_member (the_location, type_id, the_criteria); @@ -311,7 +311,7 @@ TAO::PG_Object_Group_Storable::create_member ( void TAO::PG_Object_Group_Storable::set_name (const char* group_name) { - Object_Group_File_Guard fg (*this, ACE_TEXT_ALWAYS_CHAR ("rw")); + Object_Group_File_Guard fg (*this, SFG::MUTATOR); PG_Object_Group::set_name (group_name); this->write (fg.peer ()); } @@ -319,14 +319,14 @@ TAO::PG_Object_Group_Storable::set_name (const char* group_name) const char* TAO::PG_Object_Group_Storable::get_name (void) { - Object_Group_File_Guard fg (*this, "r"); + Object_Group_File_Guard fg (*this, SFG::ACCESSOR); return PG_Object_Group::get_name (); } void TAO::PG_Object_Group_Storable::initial_populate (void) { - Object_Group_File_Guard fg (*this, "rw"); + Object_Group_File_Guard fg (*this, SFG::MUTATOR); PG_Object_Group::initial_populate (); this->write (fg.peer ()); } @@ -334,7 +334,7 @@ TAO::PG_Object_Group_Storable::initial_populate (void) void TAO::PG_Object_Group_Storable::minimum_populate (void) { - Object_Group_File_Guard fg (*this, "rw"); + Object_Group_File_Guard fg (*this, SFG::MUTATOR); PG_Object_Group::minimum_populate (); this->write (fg.peer ()); } @@ -343,14 +343,14 @@ int TAO::PG_Object_Group_Storable::has_member_at ( const PortableGroup::Location & location) { - Object_Group_File_Guard fg (*this, ACE_TEXT_ALWAYS_CHAR ("r")); + Object_Group_File_Guard fg (*this, SFG::ACCESSOR); return PG_Object_Group::has_member_at (location); } void TAO::PG_Object_Group_Storable::distribute (int value) { - Object_Group_File_Guard fg (*this, ACE_TEXT_ALWAYS_CHAR ("rw")); + Object_Group_File_Guard fg (*this, SFG::MUTATOR); PG_Object_Group::distribute (value); this->write (fg.peer ()); } @@ -359,7 +359,7 @@ CORBA::Object_ptr TAO::PG_Object_Group_Storable::get_member_reference ( const PortableGroup::Location & the_location) { - Object_Group_File_Guard fg (*this, ACE_TEXT_ALWAYS_CHAR ("r")); + Object_Group_File_Guard fg (*this, SFG::ACCESSOR); return PG_Object_Group::get_member_reference (the_location); } @@ -391,27 +391,12 @@ TAO::PG_Object_Group_Storable::read (TAO::Storable_Base & stream) ACE_CString group_name; stream >> group_name; - if (!stream.good ()) - { - stream.clear (); - throw CORBA::INTERNAL (); - } PG_Object_Group::set_name(group_name.c_str()); stream >> this->distribute_; - if (!stream.good ()) - { - stream.clear (); - throw CORBA::INTERNAL (); - } stream >> this->role_; - if (!stream.good ()) - { - stream.clear (); - throw CORBA::INTERNAL (); - } ///// primary_location_ ///// read_cdr (stream, this->primary_location_); @@ -419,11 +404,6 @@ TAO::PG_Object_Group_Storable::read (TAO::Storable_Base & stream) ///// reference_ ///// ACE_CString reference_ior; stream >> reference_ior; - if (!stream.good ()) - { - stream.clear (); - throw CORBA::INTERNAL (); - } this->reference_ = this->orb_->string_to_object (reference_ior.c_str ()); ///// tagged_component_ ///// @@ -440,11 +420,6 @@ TAO::PG_Object_Group_Storable::read (TAO::Storable_Base & stream) ///// members_ ///// int num_members; stream >> num_members; - if (!stream.good ()) - { - stream.clear (); - throw CORBA::INTERNAL (); - } this->clear_members_map (); @@ -457,12 +432,8 @@ TAO::PG_Object_Group_Storable::read (TAO::Storable_Base & stream) ///// member ///// ACE_CString member_ior; stream >> member_ior; - if (!stream.good ()) - { - stream.clear (); - throw CORBA::INTERNAL (); - } - CORBA::Object_var member = this->orb_->string_to_object (member_ior.c_str ()); + CORBA::Object_var member = + this->orb_->string_to_object (member_ior.c_str ()); if (CORBA::is_nil (member)) throw CORBA::INV_OBJREF (); @@ -473,12 +444,8 @@ TAO::PG_Object_Group_Storable::read (TAO::Storable_Base & stream) ///// factory ///// ACE_CString factory_ior; stream >> factory_ior; - if (!stream.good ()) - { - stream.clear (); - throw CORBA::INTERNAL (); - } - CORBA::Object_var obj = this->orb_->string_to_object (factory_ior.c_str ()); + CORBA::Object_var obj = + this->orb_->string_to_object (factory_ior.c_str ()); PortableGroup::GenericFactory_var factory = PortableGroup::GenericFactory::_narrow (obj.in()); @@ -489,11 +456,6 @@ TAO::PG_Object_Group_Storable::read (TAO::Storable_Base & stream) ///// is_primary ///// int is_primary; stream >> is_primary; - if (!stream.good ()) - { - stream.clear (); - throw CORBA::INTERNAL (); - } MemberInfo * info = 0; ACE_NEW_THROW_EX (info, MemberInfo(member.in (), @@ -525,7 +487,8 @@ TAO::PG_Object_Group_Storable::write (TAO::Storable_Base & stream) primary_location_cdr << PG_Object_Group::get_primary_location (); stream << primary_location_cdr; - ACE_CString reference_ior = this->orb_->object_to_string (this->reference_.in ()); + ACE_CString reference_ior = + this->orb_->object_to_string (this->reference_.in ()); stream << reference_ior; TAO_OutputCDR tagged_component_cdr; @@ -556,14 +519,16 @@ TAO::PG_Object_Group_Storable::write (TAO::Storable_Base & stream) stream << the_location_cdr; MemberInfo * member = it->item (); - ACE_CString member_ior = this->orb_->object_to_string (member->member_.in ()); + ACE_CString member_ior = + this->orb_->object_to_string (member->member_.in ()); stream << member_ior; TAO_OutputCDR location_cdr; location_cdr << member->location_; stream << location_cdr; - ACE_CString factory_ior = this->orb_->object_to_string (member->factory_.in ()); + ACE_CString factory_ior = + this->orb_->object_to_string (member->factory_.in ()); stream << factory_ior; TAO_OutputCDR factory_id_cdr; diff --git a/TAO/orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/GroupService/ObjectGroup_0 b/TAO/orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/GroupService/ObjectGroup_0 Binary files differnew file mode 100644 index 00000000000..0558ced7ed9 --- /dev/null +++ b/TAO/orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/GroupService/ObjectGroup_0 diff --git a/TAO/orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/GroupService/ObjectGroup_global b/TAO/orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/GroupService/ObjectGroup_global new file mode 100644 index 00000000000..2f1465d1598 --- /dev/null +++ b/TAO/orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/GroupService/ObjectGroup_global @@ -0,0 +1,3 @@ +1 +1 +0 diff --git a/TAO/orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/NameService/NameService b/TAO/orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/NameService/NameService new file mode 100644 index 00000000000..6b02ae41b97 --- /dev/null +++ b/TAO/orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/NameService/NameService @@ -0,0 +1,5 @@ +7 +0 +0 +6 +wi
\ No newline at end of file diff --git a/TAO/orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/NameService/NameService_0 b/TAO/orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/NameService/NameService_0 new file mode 100644 index 00000000000..d09c35a22ba --- /dev/null +++ b/TAO/orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/NameService/NameService_0 @@ -0,0 +1,5 @@ +4 +0 +1 +5 +ob
\ No newline at end of file diff --git a/TAO/orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/NameService/NameService_1 b/TAO/orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/NameService/NameService_1 new file mode 100644 index 00000000000..5c1dc2a9185 --- /dev/null +++ b/TAO/orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/NameService/NameService_1 @@ -0,0 +1,8 @@ +1 +0 +0 +6 +deep_1 +0 + +1
\ No newline at end of file diff --git a/TAO/orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/NameService/NameService_2 b/TAO/orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/NameService/NameService_2 new file mode 100644 index 00000000000..11367bed4cf --- /dev/null +++ b/TAO/orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/NameService/NameService_2 @@ -0,0 +1,5 @@ +1 +0 +0 +6 +de
\ No newline at end of file diff --git a/TAO/orbsvcs/tests/FT_Naming/FaultTolerant/run_persistence_test.pl b/TAO/orbsvcs/tests/FT_Naming/FaultTolerant/run_persistence_test.pl index 488db01a0da..86bdf56a3d8 100755 --- a/TAO/orbsvcs/tests/FT_Naming/FaultTolerant/run_persistence_test.pl +++ b/TAO/orbsvcs/tests/FT_Naming/FaultTolerant/run_persistence_test.pl @@ -8,6 +8,8 @@ eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' use lib "$ENV{ACE_ROOT}/bin"; use PerlACE::TestTarget; use Cwd; +use File::Compare; +use File::Copy; #$ENV{ACE_TEST_VERBOSE} = "1"; @@ -88,6 +90,21 @@ sub restore_output() open (STDOUT, ">&OLDOUT") or die "Can't dup OLDOUT: $!"; } +sub compare_file_with_backup($) +{ + my $file = shift; + my $backup = $file . ".bak"; + unless (-e $backup) { + print STDERR "ERROR: Backup file $backup does not exist\n"; + return 1; + } + my $result = compare ($file, $backup); + if ($result != 0) { + print STDERR "ERROR: Backup file $backup does not agree with $file\n"; + } + return $result; +} + sub run_nsgroup ($$) { my $args = shift; @@ -222,7 +239,7 @@ sub clean_persistence_dir($$) # Make sure that the directory to use to hold the naming contexts exists # and is cleaned out -sub init_naming_context_directory($$) +sub init_persistence_dir($$) { my $target = shift; my $directory_name = shift; @@ -286,8 +303,8 @@ sub persistence_test () my $client_nm_iorfile = $client->LocalFile ($nm_iorfile); print_msg("Persistence Test"); - init_naming_context_directory ($server, $name_dir ); - init_naming_context_directory ($server, $group_dir ); + init_persistence_dir ($server, $name_dir ); + init_persistence_dir ($server, $group_dir ); my $ns_args = "-ORBListenEndPoints $ns_endpoint1 ". "-ORBDebugLevel $debug_level " . @@ -338,8 +355,7 @@ sub persistence_test () exit 1; } - ##2. Create new contexts - ##3. Create a new object group + ##2. Create new contexts and new object groups print_msg("INFO: starting test server"); $server_status = $SV2->Spawn (); if ($server_status != 0) { @@ -353,7 +369,7 @@ sub persistence_test () exit 1; } - ##4. Verify the new context and object group + ##3. Creation additional contexts and object groups and verify print_msg("INFO: Starting client1"); $client_status = $CL1->SpawnWaitKill ($client->ProcessStartWaitInterval()); if ($client_status != 0) { @@ -361,7 +377,7 @@ sub persistence_test () $status = 1; } - ##5. Kill the tao_ft_naming server + ##4. Kill the tao_ft_naming server print_msg("Kill the tao_ft_naming server"); $server_status = $NS1->TerminateWaitKill ($server->ProcessStopWaitInterval()); if ($server_status != 0) { @@ -369,7 +385,7 @@ sub persistence_test () $status = 1; } - ##6. Start a new instance of the tao_ft_naming server + ##5. Start a new instance of the tao_ft_naming server print_msg("Start a new instance of the tao_ft_naming server"); $server->DeleteFile ($ns_iorfile); $NS1->Spawn (); @@ -380,7 +396,7 @@ sub persistence_test () $status = 1; } - ##7. Verify the new name, object group and member are in the tao_ft_naming repository. + ##6. Verify the new name, object group and member are in the tao_ft_naming repository. print_msg("Verify the new name, object group and member are in the tao_ft_naming repository"); print_msg("INFO: Starting client2"); $client_status = $CL2->SpawnWaitKill ($client->ProcessStartWaitInterval()); @@ -409,6 +425,194 @@ sub persistence_test () return $status; } +################################################################################ +# Validate that when a corrupt persistent file is read that the contents of the +# backup file is used instead. +################################################################################ +sub backup_restore_test () +{ + + my $num_child_contexts = 8; + my $num_object_groups = 1; + + my $previous_status = $status; + $status = 0; + + my $hostname = $server->HostName (); + my $ns_orb_port1 = 10001 + $server->RandomPort (); + my $ns_endpoint1 = "iiop://$hostname:$ns_orb_port1"; + my $default_init_ref = "-ORBDefaultInitRef corbaloc:iiop:$hostname:$ns_orb_port1"; + my $client_nm_iorfile = $client->LocalFile ($nm_iorfile); + + print_msg("Backup/Restore Test"); + init_persistence_dir ($server, $name_dir ); + init_persistence_dir ($server, $group_dir ); + + my $ns_args = "-ORBListenEndPoints $ns_endpoint1 ". + "-ORBDebugLevel $debug_level " . + "-g $nm_iorfile ". + "-o $ns_iorfile ". + "-v $group_dir ". + "-u $name_dir "; + + my $tao_ft_naming = "$ENV{TAO_ROOT}/orbsvcs/Naming_Service/tao_ft_naming"; + + my $client1_args = "--persistence " . + "--create " . + "-ORBDebugLevel $debug_level " . + "-p corbaloc:iiop:$hostname:$ns_orb_port1/NameService " . + "-r corbaloc:iiop:$hostname:$ns_orb_port1/NamingManager " . + "-b 4 " . + "-d 4 "; + + my $client2_args = "--persistence " . + "--validate " . + "-ORBDebugLevel $debug_level " . + "-p corbaloc:iiop:$hostname:$ns_orb_port1/NameService " . + "-r corbaloc:iiop:$hostname:$ns_orb_port1/NamingManager " . + "-b 4 " . + "-d 4 "; + + my $client_prog = "$startdir/client"; + + + ##1. Run one instance of tao_ft_naming service + $NS1 = $server->CreateProcess ($tao_ft_naming, $ns_args); + $CL1 = $client->CreateProcess ($client_prog, $client1_args); + $CL2 = $client->CreateProcess ($client_prog, $client2_args); + + + my $server2_args = "-ORBdebuglevel $debug_level " . + "$default_init_ref ". + "-o $sv2_iorfile "; + + $SV2 = $server2->CreateProcess ("$startdir/server", $server2_args); + + $server->DeleteFile ($ns_iorfile); + $NS1->Spawn (); + if ($server->WaitForFileTimed ($ns_iorfile, + $server->ProcessStartWaitInterval()) == -1) { + print STDERR "ERROR: cannot find file <$ns_iorfile>\n"; + $NS1->Kill (); $NS1->TimedWait (1); + exit 1; + } + + ##2. Create new contexts and new object groups + print_msg("INFO: starting test server"); + $server_status = $SV2->Spawn (); + if ($server_status != 0) { + print STDERR "ERROR: server returned $server_status\n"; + exit 1; + } + if ($server2->WaitForFileTimed ($sv_iorfile, + $server2->ProcessStartWaitInterval()) == -1) { + print STDERR "ERROR: cannot find file <$sv_iorfile>\n"; + $SV2->Kill (); $SV2->TimedWait (1); + exit 1; + } + + ##3. Creation additional contexts and object groups and verify + print_msg("INFO: Starting client1"); + $client_status = $CL1->SpawnWaitKill ($client->ProcessStartWaitInterval()); + if ($client_status != 0) { + print STDERR "ERROR: client1 returned $client_status\n"; + $status = 1; + } + + ##4. Kill the tao_ft_naming server + print_msg("Kill the tao_ft_naming server"); + $server_status = $NS1->TerminateWaitKill ($server->ProcessStopWaitInterval()); + if ($server_status != 0) { + print STDERR "ERROR: server 1 returned $server_status\n"; + $status = 1; + } + + ##4. Verify that backup files are created + + print_msg("Verifying naming context backup files"); + $file = $name_dir . "/NameService"; + if (compare_file_with_backup ($file) != 0) { + $status = 1; + } + for ($i = 0; $i < $num_child_contexts; $i++) { + $file = $name_dir . "/NameService_$i"; + if (compare_file_with_backup ($file) != 0) { + $status = 1; + } + } + + print_msg("Verifying object group backup files"); + $file = $group_dir . "/ObjectGroup_global"; + if (compare_file_with_backup ($file) != 0) { + $status = 1; + } + for ($i = 0; $i < $num_object_groups; $i++) { + $file = $group_dir . "/ObjectGroup_$i"; + if (compare_file_with_backup ($file) != 0) { + $status = 1; + } + } + + ##. Replace some of the data files with corrupt files + print_msg("Replace data files with corrupt files"); + my $corrupt_data_dir = $startdir . "/corrupt_data/"; + + my $corrupt_name_dir = $corrupt_data_dir . $name_dir . "/"; + opendir(NAMEDIR, $corrupt_name_dir); + @allfiles = grep(/^NameService/, readdir(NAMEDIR)); + closedir(NAMEDIR); + foreach $file (@allfiles) { + copy ($corrupt_name_dir . $file, $name_dir . "/" . $file) or die "Copy failed: $!\n"; + } + + my $corrupt_group_dir = $corrupt_data_dir . $group_dir . "/"; + opendir(GROUPDIR, $corrupt_group_dir); + @allfiles = grep(/^ObjectGroup/, readdir(GROUPDIR)); + closedir(GROUPDIR); + foreach $file (@allfiles) { + copy ($corrupt_group_dir . $file, $group_dir . "/" . $file) or die "Copy failed: $!\n"; + } + + ##5. Start a new instance of the tao_ft_naming server + print_msg("Start a new instance of the tao_ft_naming server"); + $server->DeleteFile ($ns_iorfile); + $NS1->Spawn (); + if ($server->WaitForFileTimed ($ns_iorfile, + $server->ProcessStartWaitInterval()) == -1) { + print STDERR "ERROR: cannot find file <$ns_iorfile>\n"; + $NS1->Kill (); $NS1->TimedWait (1); + $status = 1; + } + + ##6. Verify the new name, object group and member are in the tao_ft_naming repository. + print_msg("Verify the backup files are used when the corrupt files are read"); + print_msg("INFO: Starting client2"); + $client_status = $CL2->SpawnWaitKill ($client->ProcessStartWaitInterval()); + if ($client_status != 0) { + print STDERR "ERROR: client2 returned $client_status\n"; + $status = 1; + } + + print_msg("INFO: terminating test server"); + $server_status = $SV2->TerminateWaitKill ($server2->ProcessStopWaitInterval()); + if ($server_status != 0) { + print STDERR "ERROR: server returned $server_status\n"; + $status = 1; + } + + $server_status = $NS1->TerminateWaitKill ($server->ProcessStopWaitInterval()); + if ($server_status != 0) { + print STDERR "ERROR: server 1 returned $server_status\n"; + $status = 1; + } + + if ( $status == 0 ) { + $status = $previous_status; + } + + return $status; +} + sub print_msg($) { my $msg = shift; @@ -429,6 +633,7 @@ sub show_result($$) } my $result = persistence_test (); +my $result = backup_restore_test (); show_result($result, "Persistence Test"); diff --git a/TAO/tao/Storable_Base.cpp b/TAO/tao/Storable_Base.cpp index fc116a11620..dc588dd8db8 100644 --- a/TAO/tao/Storable_Base.cpp +++ b/TAO/tao/Storable_Base.cpp @@ -16,3 +16,82 @@ #include "tao/Storable_Base.inl" #endif /* __ACE_INLINE__ */ +TAO_BEGIN_VERSIONED_NAMESPACE_DECL + +bool TAO::Storable_Base::use_backup_default = false; + +void +TAO::Storable_Base::remove (void) +{ + if (this->use_backup_) + { + this->remove_backup (); + } + this->do_remove (); +} + +bool +TAO::Storable_Base::use_backup () +{ + return this->use_backup_; +} + +ACE_CString +TAO::Storable_Base::state_as_string (Storable_State state) +{ + ACE_CString state_string; + if (state == goodbit) + state_string = "goodbit"; + else + { + if (state & badbit) + state_string = "badbit "; + if (state & eofbit) + state_string += "eofbit "; + if (state & failbit) + state_string += "failbit"; + } + return state_string; +} + +TAO::Storable_Exception:: +Storable_Exception (Storable_Base::Storable_State state, + const ACE_CString & file_name) + : storable_state_ (state) + , file_name_ (file_name) +{ +} + +TAO::Storable_Exception:: +~Storable_Exception () +{ +} + +TAO::Storable_Base::Storable_State +TAO::Storable_Exception::get_state () const +{ + return storable_state_; +} + +const ACE_CString & +TAO::Storable_Exception::get_file_name () const +{ + return file_name_; +} + +TAO::Storable_Read_Exception:: +Storable_Read_Exception (Storable_Base::Storable_State state, + const ACE_CString & file_name) + : Storable_Exception (state, file_name) +{ +} + +TAO::Storable_Write_Exception:: +Storable_Write_Exception (Storable_Base::Storable_State state, + const ACE_CString & file_name) + : Storable_Exception (state, file_name) +{ +} + + +TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/Storable_Base.h b/TAO/tao/Storable_Base.h index 5fb3e002391..b2fdcf7fc23 100644 --- a/TAO/tao/Storable_Base.h +++ b/TAO/tao/Storable_Base.h @@ -29,16 +29,32 @@ TAO_BEGIN_VERSIONED_NAMESPACE_DECL namespace TAO { + class TAO_Export Storable_Base { public: - Storable_Base (); + + Storable_Base (bool use_backup); virtual ~Storable_Base (); - virtual void remove () = 0; + /// The process-wide default policy + /// for doing a backup when close () + /// is called. + /// The backup can then be restored if + /// restore_backup () is called. + /// The initial value for the default is false. + static bool use_backup_default; + + bool use_backup (); + + /// Remove the file that is assumed to not be open. + /// If backup are used, the backup will also be removed. + void remove(); - virtual int exists () = 0; + virtual int create_backup () = 0; + + virtual int exists() = 0; virtual int open () = 0; @@ -48,7 +64,7 @@ namespace TAO virtual int funlock (int whence, int start, int len) = 0; - virtual time_t last_changed (void) = 0; + virtual time_t last_changed(void) = 0; // Mimic a portion of the std::ios interface. We need to be able // to indicate error states from the extraction operators below. @@ -72,6 +88,8 @@ namespace TAO bool fail (void) const; + static ACE_CString state_as_string (Storable_State state); + virtual void rewind (void) = 0; virtual bool flush (void) = 0; @@ -98,11 +116,59 @@ namespace TAO virtual size_t read (size_t size, char * bytes) = 0; + virtual int restore_backup () = 0; + + protected: + + virtual void do_remove () = 0; + + /// If a backup file exists, remove it. + virtual void remove_backup () = 0; + + bool use_backup_; + private: Storable_State state_; }; + /// Base class for exceptions thrown when encountering + /// errors working with persistent files. + class TAO_Export Storable_Exception + { + public: + Storable_Exception (Storable_Base::Storable_State state, + const ACE_CString & file_name); + + virtual ~Storable_Exception (); + + Storable_Base::Storable_State get_state () const; + + const ACE_CString & get_file_name () const; + + private: + TAO::Storable_Base::Storable_State storable_state_; + ACE_CString file_name_; + }; + + /// Exception thrown when an error is encountered + /// during reading of the persistent store. + class TAO_Export Storable_Read_Exception : public Storable_Exception + { + public: + Storable_Read_Exception (Storable_Base::Storable_State state, + const ACE_CString & file_name); + }; + + /// Exception thrown when an error is encountered + /// during writing to the persistent store. + class TAO_Export Storable_Write_Exception : public Storable_Exception + { + public: + Storable_Write_Exception (Storable_Base::Storable_State state, + const ACE_CString & file_name); + }; + } TAO_END_VERSIONED_NAMESPACE_DECL diff --git a/TAO/tao/Storable_Base.inl b/TAO/tao/Storable_Base.inl index 6f43f722b01..caddbdee3e7 100644 --- a/TAO/tao/Storable_Base.inl +++ b/TAO/tao/Storable_Base.inl @@ -17,8 +17,9 @@ TAO_BEGIN_VERSIONED_NAMESPACE_DECL ACE_INLINE -TAO::Storable_Base::Storable_Base () - : state_ (goodbit) +TAO::Storable_Base::Storable_Base (bool use_backup) + : use_backup_ (use_backup) + , state_ (goodbit) { } diff --git a/TAO/tao/Storable_Factory.h b/TAO/tao/Storable_Factory.h index 216c35364d9..2532c774254 100644 --- a/TAO/tao/Storable_Factory.h +++ b/TAO/tao/Storable_Factory.h @@ -38,7 +38,9 @@ namespace TAO // Factory Methods virtual Storable_Base *create_stream(const ACE_CString & file, - const ACE_TCHAR * mode) = 0; + const ACE_TCHAR * mode, + bool use_backup = + Storable_Base::use_backup_default) = 0; }; } diff --git a/TAO/tao/Storable_File_Guard.cpp b/TAO/tao/Storable_File_Guard.cpp index 3c7139d3e71..1c20d904df9 100644 --- a/TAO/tao/Storable_File_Guard.cpp +++ b/TAO/tao/Storable_File_Guard.cpp @@ -15,21 +15,67 @@ #include "tao/SystemException.h" TAO::Storable_File_Guard:: -Storable_File_Guard (bool redundant) - : redundant_ (redundant) - , closed_ (1) +Storable_File_Guard (bool redundant, bool use_backup) + : redundant_(redundant) + , closed_(1) + , use_backup_(use_backup) +{ +} + +TAO::Storable_File_Guard:: +~Storable_File_Guard () { - ACE_TRACE (ACE_TEXT ("TAO::Storable_File_Guard::Storable_File_Guard")); } void -TAO::Storable_File_Guard::init (const char * mode) +TAO::Storable_File_Guard::init(Method_Type method_type) { - ACE_TRACE (ACE_TEXT ("TAO::Storable_File_Guard::init")); + + ACE_CString mode; + + // If backup is used then always need to open with + // write access since if the file is corrupt then + // will overwrite with backup file. + if (this->use_backup_) + { + switch (method_type) + { + case CREATE_WITH_FILE: + mode = "rw"; + break; + case CREATE_WITHOUT_FILE: + mode = "rwc"; + break; + case ACCESSOR: + mode = "rw"; + break; + case MUTATOR: + mode = "rw"; + break; + } + } + else + { + switch (method_type) + { + case CREATE_WITH_FILE: + mode = "r"; + break; + case CREATE_WITHOUT_FILE: + mode = "wc"; + break; + case ACCESSOR: + mode = "r"; + break; + case MUTATOR: + mode = "rw"; + break; + } + } // We only accept a subset of mode argument, check it rwflags_ = 0; - for ( unsigned int i = 0; i<ACE_OS::strlen (mode); i++ ) + for( unsigned int i = 0; i < mode.length (); i++ ) { switch (mode[i]) { @@ -45,25 +91,25 @@ TAO::Storable_File_Guard::init (const char * mode) if( rwflags_ <= 0 ) { errno = EINVAL; - throw CORBA::PERSIST_STORE (); + throw CORBA::PERSIST_STORE(); } // Create the stream - fl_ = this->create_stream (mode); + fl_ = this->create_stream(mode.c_str ()); if (redundant_) { - if (fl_->open () != 0) + if (fl_->open() != 0) { delete fl_; - throw CORBA::PERSIST_STORE (); + throw CORBA::PERSIST_STORE(); } // acquire a lock on it - if (fl_ -> flock (0, 0, 0) != 0) + if (fl_ -> flock(0, 0, 0) != 0) { - fl_->close (); + fl_->close(); delete fl_; - throw CORBA::INTERNAL (); + throw CORBA::INTERNAL(); } // now that the file is successfully opened and locked it must be @@ -76,18 +122,18 @@ TAO::Storable_File_Guard::init (const char * mode) if (this->object_obsolete ()) { this->mark_object_current (); - this->load_from_stream (); + this->load (); } } } else if ( ! this->is_loaded_from_stream () || (rwflags_ & mode_write) ) { - bool file_has_data = fl_->exists (); + bool file_has_data = fl_->exists(); - if (fl_->open () != 0) + if (fl_->open() != 0) { delete fl_; - throw CORBA::PERSIST_STORE (); + throw CORBA::PERSIST_STORE(); } // now that the file is successfully opened @@ -96,7 +142,7 @@ TAO::Storable_File_Guard::init (const char * mode) if (file_has_data && ! this->is_loaded_from_stream ()) { - this->load_from_stream (); + this->load (); } } else @@ -123,9 +169,14 @@ TAO::Storable_File_Guard::mark_object_current (void) void TAO::Storable_File_Guard::release (void) { - ACE_TRACE (ACE_TEXT ("TAO::Storable_File_Guard::release")); if ( ! closed_ ) { + + if (this->use_backup_ ) + { + fl_->create_backup (); + } + // If we updated the disk, save the time stamp if(redundant_) { @@ -140,9 +191,9 @@ TAO::Storable_File_Guard::release (void) } // Release the lock - fl_->funlock (0, 0, 0); + fl_->funlock(0, 0, 0); } - fl_->close (); + fl_->close(); delete fl_; closed_ = 1; } @@ -155,8 +206,61 @@ TAO::Storable_File_Guard::peer () return *fl_; } -TAO::Storable_File_Guard:: -~Storable_File_Guard () +void +TAO::Storable_File_Guard::load () { - ACE_TRACE (ACE_TEXT ("TAO::Storable_File_Guard::~Storable_File_Guard")); + if (!this->use_backup_) + { + this->load_from_stream (); + return; + } + + try + { + this->load_from_stream (); + } + catch (const Storable_Read_Exception &ex) + { + ACE_CString state_str = Storable_Base::state_as_string (ex.get_state()); + + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("TAO: (%P|%t) ERROR: State %s ") + ACE_TEXT ("encountered reading persistent ") + ACE_TEXT ("state from file\n%s\n"), + state_str.c_str (), ex.get_file_name().c_str ())); + + int result = this->fl_->restore_backup (); + + // result of 0 means OK. + if (!result) + { + + ACE_ERROR ((LM_INFO, + ACE_TEXT ("TAO: (%P|%t) Attempting to restore ") + ACE_TEXT ("from backup\n"))); + + try + { + this->load_from_stream (); + } + catch (const Storable_Read_Exception &ex) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("TAO: (%P|%t) ERROR: Unable to restore ") + ACE_TEXT ("the state from backup.\n"))); + throw; + } + ACE_ERROR ((LM_INFO, + ACE_TEXT ("TAO: (%P|%t) The state was restored ") + ACE_TEXT ("from backup.\n"))); + } + else + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("TAO: (%P|%t) ERROR: Could not read ") + ACE_TEXT ("backup file\n"))); + throw; + } + + } } diff --git a/TAO/tao/Storable_File_Guard.h b/TAO/tao/Storable_File_Guard.h index 8bc38e9f309..6b4a055be38 100644 --- a/TAO/tao/Storable_File_Guard.h +++ b/TAO/tao/Storable_File_Guard.h @@ -14,16 +14,13 @@ #ifndef TAO_STORABLE_FILE_GUARD_H #define TAO_STORABLE_FILE_GUARD_H -#include "tao/orbconf.h" -#include "tao/TAO_Export.h" +#include "tao/Storable_Base.h" TAO_BEGIN_VERSIONED_NAMESPACE_DECL namespace TAO { - class Storable_Base; - /** * @class Storable_File_Guard * @brief Base class to use with TAO_Storable_Base to synch object state @@ -38,7 +35,8 @@ namespace TAO { public: - Storable_File_Guard (bool redundant); + Storable_File_Guard (bool redundant, + bool use_backup = Storable_Base::use_backup_default); virtual ~Storable_File_Guard (); @@ -53,12 +51,31 @@ namespace TAO /// Get the underlying stream being used. TAO::Storable_Base & peer (); + /// Indicate how the state of the object is being used. + /// This is used for determine the mode for accessing + /// the persistent store. + enum Method_Type + { + + /// Construction with persistent file already existing + CREATE_WITH_FILE, + + /// Construction with persistent file not existing + CREATE_WITHOUT_FILE, + + /// Getting object state + ACCESSOR, + + /// Setting object state + MUTATOR + }; + protected: /// Should be called by constructors of derived classes - /// since can't call virtual functions below in constructor + /// since can't call the virtual functions below in constructor /// of this class. - void init (const char * mode); + void init (Method_Type method_type); /// Check if the object is current with the last update. virtual bool object_obsolete (void); @@ -82,6 +99,8 @@ namespace TAO private: + void load (); + bool redundant_; /// A flag to keep us from trying to close things more than once. @@ -90,6 +109,9 @@ namespace TAO /// The flags that we were opened with int rwflags_; + /// A flag indicating if backup/restore should be performed + bool use_backup_; + /// Symbolic values for the flags in the above enum { mode_write = 1, mode_read = 2, mode_create = 4 }; diff --git a/TAO/tao/Storable_FlatFileStream.cpp b/TAO/tao/Storable_FlatFileStream.cpp index 247b9f50698..3a5977c9dd8 100644 --- a/TAO/tao/Storable_FlatFileStream.cpp +++ b/TAO/tao/Storable_FlatFileStream.cpp @@ -25,11 +25,11 @@ namespace /// Avoids using fscanf to read an integer as any /// whitespace following the newline will be /// consumed. This could create problems if - /// the data the follows the newline is binary. + /// the data that follows the newline is binary. template<typename T> - void read_integer (const char * format, T & i, - TAO::Storable_Base::Storable_State & state, - FILE * fl) + void read_integer(const char * format, T & i, + TAO::Storable_Base::Storable_State & state, + FILE * fl) { char buf[BUFSIZ]; char * result = fgets (buf, BUFSIZ, fl); @@ -74,77 +74,114 @@ namespace } } + int file_copy(FILE *f1, FILE *f2) + { + char buffer[BUFSIZ]; + size_t n_read; + + bool all_read = false; + bool some_read = false; + + while (!all_read) + { + n_read = + ACE_OS::fread(buffer, 1, sizeof(buffer), f1); + if (n_read > 0) + { + if (ACE_OS::fwrite(buffer, 1, n_read, f2) != n_read) + return -1; + some_read = true; + } + else if (!some_read) + { + // Nothing was read + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("TAO: (%P|%t) ERROR: could not read from file\n"))); + + if (ferror (f1)) + { + ACE_ERROR ((LM_ERROR, + "%p\n", + "fread error")); + } + return -1; + } + else + { + all_read = true; + } + } + + return 0; + } + } TAO::Storable_FlatFileStream::Storable_FlatFileStream (const ACE_CString & file, - const char * mode) - : fl_ (0) + const char * mode, + bool use_backup) + : Storable_Base(use_backup) + , fl_ (0) { - ACE_TRACE ( ACE_TEXT ("TAO::Storable_FlatFileStream")); file_ = file; mode_ = mode; } TAO::Storable_FlatFileStream::~Storable_FlatFileStream () { - ACE_TRACE (ACE_TEXT ("~Storable_FlatFileStream")); if ( fl_ != 0 ) - this->close (); + this->close(); } void -TAO::Storable_FlatFileStream::remove () +TAO::Storable_FlatFileStream::do_remove () { - ACE_TRACE (ACE_TEXT ("remove")); - ACE_OS::unlink (ACE_TEXT_CHAR_TO_TCHAR (file_.c_str())); + ACE_OS::unlink(ACE_TEXT_CHAR_TO_TCHAR(file_.c_str())); } int TAO::Storable_FlatFileStream::exists () { - ACE_TRACE (ACE_TEXT ("exists")); // We could check the mode for this file, but for now just check exists - return ! ACE_OS::access (file_.c_str (), F_OK); + return ! ACE_OS::access(file_.c_str(), F_OK); } int -TAO::Storable_FlatFileStream::open () +TAO::Storable_FlatFileStream::open() { - ACE_TRACE ( ACE_TEXT ("open")); // For now, three flags exist "r", "w", and "c" int flags = 0; const char *fdmode = 0; - if( ACE_OS::strchr (mode_.c_str (), 'r') ) - if( ACE_OS::strchr (mode_.c_str (), 'w') ) - flags = O_RDWR, fdmode = "r+"; + if( ACE_OS::strchr(mode_.c_str(), 'r') ) + if( ACE_OS::strchr(mode_.c_str(), 'w') ) + flags = O_RDWR, fdmode = "w+"; else flags = O_RDONLY, fdmode = "r"; else flags = O_WRONLY, fdmode = "w"; - if( ACE_OS::strchr (mode_.c_str (), 'c') ) + if( ACE_OS::strchr(mode_.c_str(), 'c') ) flags |= O_CREAT; #ifndef ACE_WIN32 - if( ACE_OS::flock_init (&filelock_, flags, ACE_TEXT_CHAR_TO_TCHAR (file_.c_str()), 0666) != 0 ) + if( ACE_OS::flock_init (&filelock_, flags, ACE_TEXT_CHAR_TO_TCHAR(file_.c_str()), 0666) != 0 ) ACE_ERROR_RETURN ((LM_ERROR, - ACE_TEXT ("Cannot open file %s for mode %s: (%d) %s\n"), - file_.c_str (), mode_.c_str (), - errno, ACE_OS::strerror (errno)), + "Cannot open file %s for mode %s: (%d) %s\n", + file_.c_str(), mode_.c_str(), + errno, ACE_OS::strerror(errno)), -1); #else - if( (filelock_.handle_= ACE_OS::open ( - ACE_TEXT_CHAR_TO_TCHAR (file_.c_str ()), flags, 0)) == ACE_INVALID_HANDLE ) + if( (filelock_.handle_= ACE_OS::open (ACE_TEXT_CHAR_TO_TCHAR(file_.c_str()), flags, 0)) == ACE_INVALID_HANDLE ) ACE_ERROR_RETURN ((LM_ERROR, - ACE_TEXT ("Cannot open file %s for mode %s: (%d) %s\n"), - file_.c_str (), mode_.c_str (), - ACE_ERRNO_GET, ACE_OS::strerror (ACE_ERRNO_GET)), + "Cannot open file %s for mode %s: (%d) %s\n", + file_.c_str(), mode_.c_str(), + ACE_ERRNO_GET, ACE_OS::strerror(ACE_ERRNO_GET)), -1); #endif - this->fl_ = ACE_OS::fdopen (filelock_.handle_, ACE_TEXT_CHAR_TO_TCHAR (fdmode)); + this->fl_ = ACE_OS::fdopen(filelock_.handle_, ACE_TEXT_CHAR_TO_TCHAR(fdmode)); if (this->fl_ == 0) ACE_ERROR_RETURN ((LM_ERROR, - ACE_TEXT ("Cannot fdopen file %s for mode %s: (%d) %s\n"), - file_.c_str (), mode_.c_str (), - ACE_ERRNO_GET, ACE_OS::strerror (ACE_ERRNO_GET)), + "Cannot fdopen file %s for mode %s: (%d) %s\n", + file_.c_str(), mode_.c_str(), + ACE_ERRNO_GET, ACE_OS::strerror(ACE_ERRNO_GET)), -1); return 0; } @@ -152,8 +189,7 @@ TAO::Storable_FlatFileStream::open () int TAO::Storable_FlatFileStream::close() { - ACE_TRACE (ACE_TEXT ("close")); - ACE_OS::fflush (fl_); + ACE_OS::fflush(fl_); #ifndef ACE_WIN32 ACE_OS::flock_destroy (&filelock_, 0); #endif @@ -167,16 +203,15 @@ TAO::Storable_FlatFileStream::close() int TAO::Storable_FlatFileStream::flock (int whence, int start, int len) { - ACE_TRACE (ACE_TEXT ("flock")); #if defined (ACE_WIN32) ACE_UNUSED_ARG (whence); ACE_UNUSED_ARG (start); ACE_UNUSED_ARG (len); #else - if( ACE_OS::strcmp (mode_.c_str(), ACE_TEXT_ALWAYS_CHAR ("r")) == 0 ) - ACE_OS::flock_rdlock (&filelock_, whence, start, len); + if( ACE_OS::strcmp(mode_.c_str(), "r") == 0 ) + ACE_OS::flock_rdlock(&filelock_, whence, start, len); else - ACE_OS::flock_wrlock (&filelock_, whence, start, len); + ACE_OS::flock_wrlock(&filelock_, whence, start, len); #endif return 0; } @@ -184,36 +219,34 @@ TAO::Storable_FlatFileStream::flock (int whence, int start, int len) int TAO::Storable_FlatFileStream::funlock (int whence, int start, int len) { - ACE_TRACE (ACE_TEXT ("funlock")); #if defined (ACE_WIN32) ACE_UNUSED_ARG (whence); ACE_UNUSED_ARG (start); ACE_UNUSED_ARG (len); #else - ACE_OS::flock_unlock (&filelock_, whence, start, len); + ACE_OS::flock_unlock(&filelock_, whence, start, len); #endif return 0; } time_t -TAO::Storable_FlatFileStream::last_changed (void) +TAO::Storable_FlatFileStream::last_changed(void) { - ACE_TRACE (ACE_TEXT ("TAO::Storable_FlatFileStream::last_changed")); ACE_stat st; - ACE_OS::fstat (filelock_.handle_, &st); + ACE_OS::fstat(filelock_.handle_, &st); return st.st_mtime; } void TAO::Storable_FlatFileStream::rewind (void) { - return ACE_OS::rewind (this->fl_); + return ACE_OS::rewind(this->fl_); } bool TAO::Storable_FlatFileStream::flush (void) { - return ACE_OS::fflush (this->fl_); + return ACE_OS::fflush(this->fl_); } int @@ -225,9 +258,11 @@ TAO::Storable_FlatFileStream::sync (void) TAO::Storable_Base & TAO::Storable_FlatFileStream::operator << (const ACE_CString& str) { - ACE_TRACE (ACE_TEXT ("TAO::Storable_FlatFileStream::operator <<")); - ACE_OS::fprintf(this->fl_, ACE_SIZE_T_FORMAT_SPECIFIER ACE_TEXT("\n%s\n"), - str.length(), str.c_str()); + int n = + ACE_OS::fprintf(this->fl_, ACE_SIZE_T_FORMAT_SPECIFIER ACE_TEXT("\n%s\n"), + str.length(), str.c_str()); + if (n < 0) + this->throw_on_write_error (badbit); return *this; } @@ -235,25 +270,21 @@ TAO::Storable_FlatFileStream::operator << (const ACE_CString& str) TAO::Storable_Base & TAO::Storable_FlatFileStream::operator >> (ACE_CString& str) { - ACE_TRACE ( ACE_TEXT ("TAO::Storable_FlatFileStream::operator >>")); int bufSize = 0; ACE_CString::size_type const max_buf_len = ACE_Numeric_Limits<ACE_CString::size_type>::max (); - switch (fscanf (fl_, ACE_TEXT_ALWAYS_CHAR ("%d\n"), &bufSize)) + switch (fscanf(fl_, "%d\n", &bufSize)) { case 0: - this->setstate (badbit); - return *this; + this->throw_on_read_error (badbit); case EOF: - this->setstate (eofbit); - return *this; + this->throw_on_read_error (eofbit); } if (bufSize < 0 || static_cast<ACE_CString::size_type> (bufSize) >= max_buf_len) { - this->setstate (badbit); - return *this; + this->throw_on_read_error (badbit); } { ACE_Auto_Basic_Array_Ptr<char> str_array (new char[bufSize + 1]); @@ -263,8 +294,7 @@ TAO::Storable_FlatFileStream::operator >> (ACE_CString& str) this->fl_) == 0 && bufSize != 0) { - this->setstate (badbit); - return *this; + this->throw_on_read_error (badbit); } str = ACE_CString (str_array.get (), 0, false); } @@ -275,19 +305,18 @@ TAO::Storable_FlatFileStream::operator >> (ACE_CString& str) TAO::Storable_Base & TAO::Storable_FlatFileStream::operator << (int i) { - ACE_TRACE (ACE_TEXT ("TAO::Storable_FlatFileStream::operator <<")); - ACE_OS::fprintf (this->fl_, ACE_TEXT ("%d\n"), i); + int n = ACE_OS::fprintf (this->fl_, "%d\n", i); + if (n < 0) + this->throw_on_write_error (badbit); return *this; } TAO::Storable_Base & TAO::Storable_FlatFileStream::operator >> (int &i) { - ACE_TRACE (ACE_TEXT ("TAO::Storable_FlatFileStream::operator >>")); - Storable_State state = this->rdstate (); - read_integer (ACE_TEXT_ALWAYS_CHAR ("%d\n"), i, state, fl_); - this->setstate (state); + read_integer ("%d\n", i, state, fl_); + this->throw_on_read_error (state); return *this; } @@ -295,19 +324,18 @@ TAO::Storable_FlatFileStream::operator >> (int &i) TAO::Storable_Base & TAO::Storable_FlatFileStream::operator << (unsigned int i) { - ACE_TRACE (ACE_TEXT ("TAO::Storable_FlatFileStream::operator <<")); - ACE_OS::fprintf (this->fl_, ACE_TEXT ("%u\n"), i); + int n = ACE_OS::fprintf (this->fl_, "%u\n", i); + if (n < 0) + this->throw_on_write_error (badbit); return *this; } TAO::Storable_Base & TAO::Storable_FlatFileStream::operator >> (unsigned int &i) { - ACE_TRACE (ACE_TEXT ("TAO::Storable_FlatFileStream::operator >>")); - Storable_State state = this->rdstate (); - read_integer (ACE_TEXT_ALWAYS_CHAR ("%u\n"), i, state, fl_); - this->setstate (state); + read_integer ("%u\n", i, state, fl_); + this->throw_on_read_error (state); return *this; } @@ -315,8 +343,6 @@ TAO::Storable_FlatFileStream::operator >> (unsigned int &i) TAO::Storable_Base & TAO::Storable_FlatFileStream::operator << (const TAO_OutputCDR & cdr) { - ACE_TRACE (ACE_TEXT ("TAO::Storable_FlatFileStream::operator <<")); - unsigned int length = cdr.total_length (); *this << length; for (const ACE_Message_Block *i = cdr.begin (); i != 0; i = i->cont ()) @@ -340,8 +366,84 @@ TAO::Storable_FlatFileStream::read (size_t size, char * bytes) return ACE_OS::fread (bytes, size, 1, fl_); } +ACE_CString +TAO::Storable_FlatFileStream::backup_file_name () +{ + return file_ + ".bak"; +} + +int +TAO::Storable_FlatFileStream::create_backup () +{ + FILE * backup = ACE_OS::fopen (this->backup_file_name ().c_str (), "w"); + this->rewind(); + int result = file_copy(this->fl_, backup); + if (result != 0) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("TAO: (%P|%t) ERROR: Unable to create backup ") + ACE_TEXT ("of file\n%s\n"), file_.c_str ())); + } + ACE_OS::fclose (backup); + return result; +} + +void +TAO::Storable_FlatFileStream::remove_backup () +{ + ACE_CString backup_name = this->backup_file_name (); + + if (ACE_OS::access (ACE_TEXT_CHAR_TO_TCHAR (backup_name.c_str ()), F_OK) == 0) + { + ACE_OS::unlink (ACE_TEXT_CHAR_TO_TCHAR (backup_name.c_str ())); + } +} + +int +TAO::Storable_FlatFileStream::restore_backup () +{ + ACE_CString backup_name = this->backup_file_name ().c_str (); + + if (ACE_OS::access (ACE_TEXT_CHAR_TO_TCHAR (backup_name.c_str ()), F_OK)) + return -1; + + FILE * backup = ACE_OS::fopen (ACE_TEXT_CHAR_TO_TCHAR (backup_name.c_str ()), + "r"); + this->rewind(); + int result = file_copy(backup, this->fl_); + ACE_OS::fclose (backup); + this->flush (); + this->clear (); + return result; +} + +void +TAO::Storable_FlatFileStream::throw_on_read_error (Storable_State state) + throw (Storable_Read_Exception) +{ + this->setstate (state); + + if (!this->good ()) + { + throw Storable_Read_Exception (this->rdstate (), this->file_); + } +} + +void +TAO::Storable_FlatFileStream::throw_on_write_error (Storable_State state) + throw (Storable_Write_Exception) +{ + this->setstate (state); + + if (!this->good ()) + { + throw Storable_Write_Exception (this->rdstate (), this->file_); + } +} + TAO::Storable_FlatFileFactory::Storable_FlatFileFactory(const ACE_CString & directory) -: directory_(directory) + : Storable_Factory () + , directory_(directory) { } @@ -357,16 +459,16 @@ TAO::Storable_FlatFileFactory::get_directory () const TAO::Storable_Base * TAO::Storable_FlatFileFactory::create_stream (const ACE_CString & file, - const ACE_TCHAR * mode) + const ACE_TCHAR * mode, + bool use_backup) { - ACE_TRACE (ACE_TEXT ("TAO::Storable_FlatFileFactory::create_stream")); TAO::Storable_Base *stream = 0; - ACE_CString path = this->directory_ + ACE_TEXT ("/") + file; + ACE_CString path = this->directory_ + "/" + file; ACE_NEW_RETURN (stream, - TAO::Storable_FlatFileStream ( - path, - ACE_TEXT_ALWAYS_CHAR (mode)), - 0); + TAO::Storable_FlatFileStream(path, + ACE_TEXT_ALWAYS_CHAR (mode), + use_backup), + 0); return stream; } diff --git a/TAO/tao/Storable_FlatFileStream.h b/TAO/tao/Storable_FlatFileStream.h index 1ebe4c68b52..10e5a9e4425 100644 --- a/TAO/tao/Storable_FlatFileStream.h +++ b/TAO/tao/Storable_FlatFileStream.h @@ -35,11 +35,11 @@ namespace TAO { public: - Storable_FlatFileStream (const ACE_CString & file, const char * mode); - virtual ~Storable_FlatFileStream (); + Storable_FlatFileStream(const ACE_CString & file, const char * mode, + bool use_backup = + Storable_Base::use_backup_default); - /// Remove a file by name (file is not open) - virtual void remove (); + virtual ~Storable_FlatFileStream(); /// Check if a file exists on disk (file is not open) virtual int exists (); @@ -47,7 +47,7 @@ namespace TAO /// Open a file (the remaining methods below all require an open file) virtual int open (); - /// Close an open file + /// Acquire a file lock virtual int close (); /// Acquire a file lock @@ -85,7 +85,30 @@ namespace TAO virtual size_t read (size_t size, char * bytes); + virtual int restore_backup (); + + protected: + + virtual void do_remove (); + + virtual void remove_backup (); + + virtual int create_backup (); + private: + + /// Throw a Storable_Read_Exception if the state + /// is not good due to a read error. + void throw_on_read_error (Storable_State state) + throw (Storable_Read_Exception); + + /// Throw a Storable_Write_Exception if the state + /// is not good due to a write error. + void throw_on_write_error (Storable_State state) + throw (Storable_Write_Exception); + + ACE_CString backup_file_name (); + ACE_OS::ace_flock_t filelock_; FILE* fl_; ACE_CString file_; @@ -98,7 +121,7 @@ namespace TAO /// @param directory Directory to contain file passed in /// create_stream (). The directory is assumed to already exist. - Storable_FlatFileFactory (const ACE_CString & directory); + Storable_FlatFileFactory(const ACE_CString & directory); const ACE_CString & get_directory () const; @@ -108,7 +131,9 @@ namespace TAO /// Create the stream that can operate on a disk file virtual Storable_Base *create_stream (const ACE_CString & file, - const ACE_TCHAR * mode); + const ACE_TCHAR * mode, + bool use_backup = + Storable_Base::use_backup_default); private: ACE_CString directory_; diff --git a/TAO/tests/Storable/Savable.cpp b/TAO/tests/Storable/Savable.cpp index 80adda4e8b1..6ec1318a6ae 100644 --- a/TAO/tests/Storable/Savable.cpp +++ b/TAO/tests/Storable/Savable.cpp @@ -11,7 +11,7 @@ class Savable_File_Guard: public TAO::Storable_File_Guard { public: - Savable_File_Guard (Savable & savable, const char *mode); + Savable_File_Guard (Savable & savable, Method_Type method_type); ~Savable_File_Guard (); @@ -29,11 +29,19 @@ private: Savable & savable_; }; -Savable_File_Guard::Savable_File_Guard (Savable & savable, const char * mode) +Savable_File_Guard::Savable_File_Guard (Savable & savable, + Method_Type method_type) : TAO::Storable_File_Guard(false) , savable_(savable) { - this->init(mode); + try + { + this->init(method_type); + } + catch (TAO::Storable_Read_Exception &) + { + throw Savable_Exception(); + } } Savable_File_Guard::~Savable_File_Guard () @@ -73,6 +81,8 @@ Savable_File_Guard::create_stream (const char * mode) return savable_.storable_factory_.create_stream ("test.dat", mode); } +typedef TAO::Storable_File_Guard SFG; + Savable::Savable (TAO::Storable_Factory & storable_factory) : storable_factory_(storable_factory) , loaded_from_stream_ (false) @@ -90,14 +100,15 @@ Savable::Savable (TAO::Storable_Factory & storable_factory) } } - ACE_Auto_Ptr<TAO::Storable_Base> stream (storable_factory_.create_stream("test.dat", "r")); + ACE_Auto_Ptr<TAO::Storable_Base> + stream (storable_factory_.create_stream("test.dat", "r")); if (stream->exists ()) { - Savable_File_Guard fg(*this, "r"); + Savable_File_Guard fg(*this, SFG::CREATE_WITH_FILE); } else { - Savable_File_Guard fg(*this, "wc"); + Savable_File_Guard fg(*this, SFG::CREATE_WITHOUT_FILE); this->write (fg.peer ()); } } @@ -120,27 +131,14 @@ void Savable::read (TAO::Storable_Base & stream) { stream.rewind (); - if (!stream.good ()) - throw Storable_Exception (stream.rdstate ()); for (int index = 0; index < 2; ++index) { stream >> this->string_[index]; - if (!stream.good ()) - throw Storable_Exception (stream.rdstate ()); - stream >> this->i_[index]; - if (!stream.good ()) - throw Storable_Exception (stream.rdstate ()); - stream >> this->ui_[index]; - if (!stream.good ()) - throw Storable_Exception (stream.rdstate ()); - stream >> this->bytes_size_[index]; stream.read (this->bytes_size_[index], this->bytes_[index]); - if (!stream.good ()) - throw Storable_Exception (stream.rdstate ()); } } @@ -148,29 +146,14 @@ void Savable::write (TAO::Storable_Base & stream) { stream.rewind (); - if (!stream.good ()) - throw Storable_Exception (stream.rdstate ()); for (int index = 0; index < 2; ++index) { stream << this->string_[index]; - if (!stream.good ()) - throw Storable_Exception (stream.rdstate ()); - stream << this->i_[index]; - if (!stream.good ()) - throw Storable_Exception (stream.rdstate ()); - stream << this->ui_[index]; - if (!stream.good ()) - throw Storable_Exception (stream.rdstate ()); - stream << this->bytes_size_[index]; - if (!stream.good ()) - throw Storable_Exception (stream.rdstate ()); stream.write (this->bytes_size_[index], this->bytes_[index]); - if (!stream.good ()) - throw Storable_Exception (stream.rdstate ()); } stream.flush (); @@ -179,7 +162,7 @@ Savable::write (TAO::Storable_Base & stream) void Savable::string_set (int index, const ACE_CString &s) { - Savable_File_Guard fg(*this, "rw"); + Savable_File_Guard fg(*this, SFG::MUTATOR); this->string_[index] = s; this->write (fg.peer ()); } @@ -187,14 +170,14 @@ Savable::string_set (int index, const ACE_CString &s) const ACE_CString & Savable::string_get (int index) { - Savable_File_Guard fg(*this, "r"); + Savable_File_Guard fg(*this, SFG::ACCESSOR); return this->string_[index]; } void Savable::int_set (int index, int i) { - Savable_File_Guard fg(*this, "rw"); + Savable_File_Guard fg(*this, SFG::MUTATOR); this->i_[index] = i; this->write (fg.peer ()); } @@ -202,14 +185,14 @@ Savable::int_set (int index, int i) int Savable::int_get (int index) { - Savable_File_Guard fg(*this, "r"); + Savable_File_Guard fg(*this, SFG::ACCESSOR); return this->i_[index]; } void Savable::unsigned_int_set (int index, unsigned int ui) { - Savable_File_Guard fg(*this, "rw"); + Savable_File_Guard fg(*this, SFG::MUTATOR); this->ui_[index] = ui; this->write (fg.peer ()); } @@ -217,14 +200,14 @@ Savable::unsigned_int_set (int index, unsigned int ui) unsigned int Savable::unsigned_int_get (int index) { - Savable_File_Guard fg(*this, "r"); + Savable_File_Guard fg(*this, SFG::ACCESSOR); return this->ui_[index]; } void Savable::bytes_set (int index, int size, char * bytes) { - Savable_File_Guard fg(*this, "rw"); + Savable_File_Guard fg(*this, SFG::MUTATOR); this->bytes_size_[index] = size; for (int i = 0; i < this->bytes_size_[index]; ++i) { @@ -236,7 +219,7 @@ Savable::bytes_set (int index, int size, char * bytes) int Savable::bytes_get (int index, char * bytes) { - Savable_File_Guard fg(*this, "r"); + Savable_File_Guard fg(*this, SFG::ACCESSOR); for (int i = 0; i < this->bytes_size_[index]; ++i) { bytes[i] = this->bytes_[index][i]; diff --git a/TAO/tests/Storable/Savable.h b/TAO/tests/Storable/Savable.h index 1eccc1ed6de..c227e90639e 100644 --- a/TAO/tests/Storable/Savable.h +++ b/TAO/tests/Storable/Savable.h @@ -9,22 +9,8 @@ namespace TAO class Storable_Factory; } -class Storable_Exception +class Savable_Exception { - public: - - Storable_Exception(TAO::Storable_Base::Storable_State state) - : stream_state_(state) - { - } - - TAO::Storable_Base::Storable_State get_state () - { - return stream_state_; - } - - private: - TAO::Storable_Base::Storable_State stream_state_; }; /// A simple class to use for testing whose contents diff --git a/TAO/tests/Storable/data_files/bad_binary.dat b/TAO/tests/Storable/data_files/bad_binary.dat new file mode 100644 index 00000000000..eda0d4e6b50 --- /dev/null +++ b/TAO/tests/Storable/data_files/bad_binary.dat @@ -0,0 +1,6 @@ +11 +test_string +-100 +100 +8 +
\ No newline at end of file diff --git a/TAO/tests/Storable/data_files/bad_int.dat b/TAO/tests/Storable/data_files/bad_int.dat new file mode 100644 index 00000000000..19e69d4a464 --- /dev/null +++ b/TAO/tests/Storable/data_files/bad_int.dat @@ -0,0 +1,3 @@ +11 +test_string +-10
\ No newline at end of file diff --git a/TAO/tests/Storable/data_files/bad_string.dat b/TAO/tests/Storable/data_files/bad_string.dat new file mode 100644 index 00000000000..0519db270cc --- /dev/null +++ b/TAO/tests/Storable/data_files/bad_string.dat @@ -0,0 +1,2 @@ +11 +test_st
\ No newline at end of file diff --git a/TAO/tests/Storable/data_files/bad_unsigned_int.dat b/TAO/tests/Storable/data_files/bad_unsigned_int.dat new file mode 100644 index 00000000000..c3dcc1cdc45 --- /dev/null +++ b/TAO/tests/Storable/data_files/bad_unsigned_int.dat @@ -0,0 +1,4 @@ +11 +test_string +-100 +10
\ No newline at end of file diff --git a/TAO/tests/Storable/data_files/good.dat b/TAO/tests/Storable/data_files/good.dat new file mode 100644 index 00000000000..a34d7bdac3e --- /dev/null +++ b/TAO/tests/Storable/data_files/good.dat @@ -0,0 +1,11 @@ +11 +test_string +-100 +100 +8 + 11 +test_string +-100 +100 +8 +
\ No newline at end of file diff --git a/TAO/tests/Storable/run_test.pl b/TAO/tests/Storable/run_test.pl index ce8de975046..137da7af005 100755 --- a/TAO/tests/Storable/run_test.pl +++ b/TAO/tests/Storable/run_test.pl @@ -7,39 +7,91 @@ eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' use lib "$ENV{ACE_ROOT}/bin"; use PerlACE::TestTarget; +use File::Copy; + +my $status = 0; my $test1 = PerlACE::TestTarget::create_target (1) || die "Create target 1 failed\n"; my $persistent_file = "test.dat"; - $test1->DeleteFile ($persistent_file); -$T1 = $test1->CreateProcess ("test", "-i 0"); +my $num_loops = 10; + +$T1 = $test1->CreateProcess ("test", "-i 0 -n $num_loops"); my $test2 = PerlACE::TestTarget::create_target (2) || die "Create target 1 failed\n"; -$T2 = $test2->CreateProcess ("test", "-i 1"); +$T2 = $test2->CreateProcess ("test", "-i 1 -n $num_loops"); $test1_status = $T1->Spawn (); if ($test1_status != 0) { print STDERR "ERROR: test 1 returned $test1_status\n"; - exit 1; + $status = 1; } $test2_status = $T2->SpawnWaitKill ($test2->ProcessStartWaitInterval()); if ($test2_status != 0) { print STDERR "ERROR: test 2 returned $test2_status\n"; - exit 1; + $status = 1; } - $test1_status = $T1->WaitKill ($test1->ProcessStopWaitInterval()); if ($test1_status != 0) { print STDERR "ERROR: test 1 returned $test1_status\n"; - exit 1; + $status = 1; } $test1->DeleteFile ($persistent_file); + +sub test_backup_recovery($) +{ + my $bad_file = shift; + + my $status = 0; + + print STDERR "Testing recovery of backup file for $bad_file.\n"; + + my $backup_file = "test.dat.bak"; + copy($bad_file, "test.dat") or die "Copy failed: $!"; + copy("data_files/good.dat", $backup_file) or die "Copy failed: $!"; + + $T = $test1->CreateProcess ("test", "-b"); + my $test_status = $T->SpawnWaitKill ($test1->ProcessStartWaitInterval()); + if ($test_status != 0) { + $status = 1; + print STDERR "ERROR: Backup recovery test using $bad_file failed\n"; + } + else { + print STDERR "Recovery successful\n"; + } + + if (-e $backup_file) { + $test1->DeleteFile ($backup_file); + } + else { + $status = 1; + print STDERR "ERROR: Backup file was not created\n"; + } + $test1->DeleteFile ($persistent_file); + + return $status; +} + +@bad_files = ( + "data_files/bad_binary.dat", + "data_files/bad_int.dat", + "data_files/bad_string.dat", + "data_files/bad_unsigned_int.dat" + ); + +foreach $bad_file (@bad_files) { + if (test_backup_recovery ($bad_file) != 0) { + $status = 1; + } +} + +exit $status diff --git a/TAO/tests/Storable/test.cpp b/TAO/tests/Storable/test.cpp index c9ed11132df..9ca675a754a 100644 --- a/TAO/tests/Storable/test.cpp +++ b/TAO/tests/Storable/test.cpp @@ -19,14 +19,15 @@ const ACE_TCHAR *persistence_file = ACE_TEXT("test.dat"); -int num_loops = 10; +int num_loops = 1; int sleep_msecs = 100; int write_index = 0; +bool use_backup = false; int parse_args (int argc, ACE_TCHAR *argv[]) { - ACE_Get_Opt get_opts (argc, argv, ACE_TEXT("n:s:i:")); + ACE_Get_Opt get_opts (argc, argv, ACE_TEXT("n:s:i:b")); int c; while ((c = get_opts ()) != -1) @@ -44,6 +45,10 @@ parse_args (int argc, ACE_TCHAR *argv[]) write_index = ACE_OS::atoi (get_opts.opt_arg ()); break; + case 'b': + use_backup = true; + break; + case '?': default: ACE_ERROR_RETURN ((LM_ERROR, @@ -51,6 +56,7 @@ parse_args (int argc, ACE_TCHAR *argv[]) ACE_TEXT("-n <number-of-loops> ") ACE_TEXT("-s <milliseconds-to-sleep-in-loop> ") ACE_TEXT("-i <index-used-for-writing> ") + ACE_TEXT("-b (use backup) ") ACE_TEXT("\n"), argv [0]), -1); @@ -71,11 +77,15 @@ parse_args (int argc, ACE_TCHAR *argv[]) int ACE_TMAIN(int argc, ACE_TCHAR *argv[]) { + int exit_status = 0; + if (parse_args (argc, argv) != 0) return 1; int read_index = write_index ? 0 : 1; + TAO::Storable_Base::use_backup_default = use_backup; + TAO::Storable_FlatFileFactory factory ("./"); ACE_CString str_write_value = "test_string"; @@ -148,11 +158,25 @@ ACE_TMAIN(int argc, ACE_TCHAR *argv[]) } - catch (Storable_Exception &ex) + catch (Savable_Exception &) + { + std::cout << "Savable_Exception thrown" << std::endl; + exit_status = 1; + } + + catch (TAO::Storable_Read_Exception &ex) { - std::cout << "Storable_Exception thrown with state " << + std::cout << "TAO::Storable_Read_Exception thrown with state " << ex.get_state () << std::endl; + exit_status = 1; } - return 0; + catch (TAO::Storable_Write_Exception &ex) + { + std::cout << "TAO::Storable_Write_Exception thrown with state " << + ex.get_state () << std::endl; + exit_status = 1; + } + + return exit_status; } |