summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorharrisb <harrisb@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2013-01-27 19:28:50 +0000
committerharrisb <harrisb@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2013-01-27 19:28:50 +0000
commitace6321eaa7ac291095daa685dd14229e8b9314b (patch)
tree3ada426b029cf0473457e8ed26a8b25a31eb6d15
parentb33919c4055efb00b753da39e5c9878fdb7b334e (diff)
downloadATCD-ace6321eaa7ac291095daa685dd14229e8b9314b.tar.gz
Sun Jan 27 18:57:35 UTC 2013 Byron Harris <harrisb@ociweb.com>
-rw-r--r--TAO/OCI_RE_ChangeLog64
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/FaultTolerant/FT_Naming_Server.cpp11
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context.cpp63
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context.h2
-rw-r--r--TAO/orbsvcs/orbsvcs/Naming/Storable_Naming_Context_ReaderWriter.cpp128
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Group_List_Store.cpp38
-rw-r--r--TAO/orbsvcs/orbsvcs/PortableGroup/PG_Object_Group_Storable.cpp113
-rw-r--r--TAO/orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/GroupService/ObjectGroup_0bin0 -> 4858 bytes
-rw-r--r--TAO/orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/GroupService/ObjectGroup_global3
-rw-r--r--TAO/orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/NameService/NameService5
-rw-r--r--TAO/orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/NameService/NameService_05
-rw-r--r--TAO/orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/NameService/NameService_18
-rw-r--r--TAO/orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/NameService/NameService_25
-rwxr-xr-xTAO/orbsvcs/tests/FT_Naming/FaultTolerant/run_persistence_test.pl223
-rw-r--r--TAO/tao/Storable_Base.cpp79
-rw-r--r--TAO/tao/Storable_Base.h74
-rw-r--r--TAO/tao/Storable_Base.inl5
-rw-r--r--TAO/tao/Storable_Factory.h4
-rw-r--r--TAO/tao/Storable_File_Guard.cpp154
-rw-r--r--TAO/tao/Storable_File_Guard.h36
-rw-r--r--TAO/tao/Storable_FlatFileStream.cpp264
-rw-r--r--TAO/tao/Storable_FlatFileStream.h39
-rw-r--r--TAO/tests/Storable/Savable.cpp67
-rw-r--r--TAO/tests/Storable/Savable.h16
-rw-r--r--TAO/tests/Storable/data_files/bad_binary.dat6
-rw-r--r--TAO/tests/Storable/data_files/bad_int.dat3
-rw-r--r--TAO/tests/Storable/data_files/bad_string.dat2
-rw-r--r--TAO/tests/Storable/data_files/bad_unsigned_int.dat4
-rw-r--r--TAO/tests/Storable/data_files/good.dat11
-rwxr-xr-xTAO/tests/Storable/run_test.pl66
-rw-r--r--TAO/tests/Storable/test.cpp34
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
new file mode 100644
index 00000000000..0558ced7ed9
--- /dev/null
+++ b/TAO/orbsvcs/tests/FT_Naming/FaultTolerant/corrupt_data/GroupService/ObjectGroup_0
Binary files differ
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;
}