summaryrefslogtreecommitdiff
path: root/TAO/tao/Storable_FlatFileStream.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'TAO/tao/Storable_FlatFileStream.cpp')
-rw-r--r--TAO/tao/Storable_FlatFileStream.cpp475
1 files changed, 475 insertions, 0 deletions
diff --git a/TAO/tao/Storable_FlatFileStream.cpp b/TAO/tao/Storable_FlatFileStream.cpp
new file mode 100644
index 00000000000..3a5977c9dd8
--- /dev/null
+++ b/TAO/tao/Storable_FlatFileStream.cpp
@@ -0,0 +1,475 @@
+// -*- C++ -*-
+
+//=============================================================================
+/**
+ * @file Storable_FlatFileStream.cpp
+ *
+ * $Id$
+ *
+ * @author Marina Spivak <marina@cs.wustl.edu>
+ * @author Byron Harris <harrisb@ociweb.com>
+ */
+//=============================================================================
+
+#include "tao/Storable_FlatFileStream.h"
+
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_fcntl.h"
+#include "ace/OS_NS_sys_stat.h"
+#include "ace/Numeric_Limits.h"
+
+TAO_BEGIN_VERSIONED_NAMESPACE_DECL
+
+namespace
+{
+ /// Avoids using fscanf to read an integer as any
+ /// whitespace following the newline will be
+ /// consumed. This could create problems if
+ /// 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)
+ {
+ char buf[BUFSIZ];
+ char * result = fgets (buf, BUFSIZ, fl);
+
+ if (result == 0)
+ {
+ if (feof (fl))
+ {
+ state = TAO::Storable_Base::eofbit;
+ return;
+ }
+ state = TAO::Storable_Base::badbit;
+ return;
+ }
+
+ /// Consume any starting newline, as fscanf would
+ /// do.
+ if (buf[0] == '\n')
+ {
+ result = fgets (buf, BUFSIZ, fl);
+ }
+
+ if (result == 0)
+ {
+ if (feof (fl))
+ {
+ state = TAO::Storable_Base::eofbit;
+ return;
+ }
+ state = TAO::Storable_Base::badbit;
+ return;
+ }
+
+ switch (sscanf (buf, format, &i))
+ {
+ case 0:
+ state = TAO::Storable_Base::badbit;
+ return;
+ case EOF:
+ state = TAO::Storable_Base::eofbit;
+ return;
+ }
+ }
+
+ 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,
+ bool use_backup)
+ : Storable_Base(use_backup)
+ , fl_ (0)
+{
+ file_ = file;
+ mode_ = mode;
+}
+
+TAO::Storable_FlatFileStream::~Storable_FlatFileStream ()
+{
+ if ( fl_ != 0 )
+ this->close();
+}
+
+void
+TAO::Storable_FlatFileStream::do_remove ()
+{
+ ACE_OS::unlink(ACE_TEXT_CHAR_TO_TCHAR(file_.c_str()));
+}
+
+int
+TAO::Storable_FlatFileStream::exists ()
+{
+ // We could check the mode for this file, but for now just check exists
+ return ! ACE_OS::access(file_.c_str(), F_OK);
+}
+
+int
+TAO::Storable_FlatFileStream::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 = "w+";
+ else
+ flags = O_RDONLY, fdmode = "r";
+ else
+ flags = O_WRONLY, fdmode = "w";
+ 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 )
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "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 )
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "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));
+ if (this->fl_ == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "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;
+}
+
+int
+TAO::Storable_FlatFileStream::close()
+{
+ ACE_OS::fflush(fl_);
+#ifndef ACE_WIN32
+ ACE_OS::flock_destroy (&filelock_, 0);
+#endif
+ ACE_OS::fclose (fl_); // even though flock_destroy closes the handle
+ // we still need to destroy the FILE*
+
+ fl_ = 0;
+ return 0;
+}
+
+int
+TAO::Storable_FlatFileStream::flock (int whence, int start, int len)
+{
+#if defined (ACE_WIN32)
+ ACE_UNUSED_ARG (whence);
+ ACE_UNUSED_ARG (start);
+ ACE_UNUSED_ARG (len);
+#else
+ 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);
+#endif
+ return 0;
+}
+
+int
+TAO::Storable_FlatFileStream::funlock (int whence, int start, int len)
+{
+#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);
+#endif
+ return 0;
+}
+
+time_t
+TAO::Storable_FlatFileStream::last_changed(void)
+{
+ ACE_stat st;
+ ACE_OS::fstat(filelock_.handle_, &st);
+ return st.st_mtime;
+}
+
+void
+TAO::Storable_FlatFileStream::rewind (void)
+{
+ return ACE_OS::rewind(this->fl_);
+}
+
+bool
+TAO::Storable_FlatFileStream::flush (void)
+{
+ return ACE_OS::fflush(this->fl_);
+}
+
+int
+TAO::Storable_FlatFileStream::sync (void)
+{
+ return ACE_OS::fsync (this->filelock_.handle_);
+}
+
+TAO::Storable_Base &
+TAO::Storable_FlatFileStream::operator << (const ACE_CString& 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;
+}
+
+TAO::Storable_Base &
+TAO::Storable_FlatFileStream::operator >> (ACE_CString& str)
+{
+ int bufSize = 0;
+ ACE_CString::size_type const max_buf_len =
+ ACE_Numeric_Limits<ACE_CString::size_type>::max ();
+ switch (fscanf(fl_, "%d\n", &bufSize))
+ {
+ case 0:
+ this->throw_on_read_error (badbit);
+ case EOF:
+ this->throw_on_read_error (eofbit);
+ }
+
+ if (bufSize < 0
+ || static_cast<ACE_CString::size_type> (bufSize) >= max_buf_len)
+ {
+ this->throw_on_read_error (badbit);
+ }
+ {
+ ACE_Auto_Basic_Array_Ptr<char> str_array (new char[bufSize + 1]);
+ str_array[0] = '\0';
+ if (ACE_OS::fgets (ACE_TEXT_CHAR_TO_TCHAR (str_array.get ()),
+ bufSize + 1,
+ this->fl_) == 0
+ && bufSize != 0)
+ {
+ this->throw_on_read_error (badbit);
+ }
+ str = ACE_CString (str_array.get (), 0, false);
+ }
+
+ return *this;
+}
+
+TAO::Storable_Base &
+TAO::Storable_FlatFileStream::operator << (int 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)
+{
+ Storable_State state = this->rdstate ();
+ read_integer ("%d\n", i, state, fl_);
+ this->throw_on_read_error (state);
+
+ return *this;
+}
+
+TAO::Storable_Base &
+TAO::Storable_FlatFileStream::operator << (unsigned int 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)
+{
+ Storable_State state = this->rdstate ();
+ read_integer ("%u\n", i, state, fl_);
+ this->throw_on_read_error (state);
+
+ return *this;
+}
+
+TAO::Storable_Base &
+TAO::Storable_FlatFileStream::operator << (const TAO_OutputCDR & cdr)
+{
+ unsigned int length = cdr.total_length ();
+ *this << length;
+ for (const ACE_Message_Block *i = cdr.begin (); i != 0; i = i->cont ())
+ {
+ const char *bytes = i->rd_ptr ();
+ size_t len = i->length ();
+ this->write (len, bytes);
+ }
+ return *this;
+}
+
+size_t
+TAO::Storable_FlatFileStream::write (size_t size, const char * bytes)
+{
+ return ACE_OS::fwrite (bytes, size, 1, fl_);
+}
+
+size_t
+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)
+ : Storable_Factory ()
+ , directory_(directory)
+{
+}
+
+TAO::Storable_FlatFileFactory::~Storable_FlatFileFactory()
+{
+}
+
+const ACE_CString &
+TAO::Storable_FlatFileFactory::get_directory () const
+{
+ return directory_;
+}
+
+TAO::Storable_Base *
+TAO::Storable_FlatFileFactory::create_stream (const ACE_CString & file,
+ const ACE_TCHAR * mode,
+ bool use_backup)
+{
+ TAO::Storable_Base *stream = 0;
+ ACE_CString path = this->directory_ + "/" + file;
+ ACE_NEW_RETURN (stream,
+ TAO::Storable_FlatFileStream(path,
+ ACE_TEXT_ALWAYS_CHAR (mode),
+ use_backup),
+ 0);
+ return stream;
+}
+
+TAO_END_VERSIONED_NAMESPACE_DECL