Browse Source

[2831] more documentation and some more tests

JINMEI Tatuya 12 years ago
parent
commit
2fb93c012e

+ 14 - 1
src/lib/util/memory_segment.h

@@ -22,18 +22,26 @@
 namespace isc {
 namespace isc {
 namespace util {
 namespace util {
 
 
+/// \brief Exception that can be thrown on constructing a MemorySegment
+/// object.
 class MemorySegmentOpenError : public Exception {
 class MemorySegmentOpenError : public Exception {
 public:
 public:
     MemorySegmentOpenError(const char* file, size_t line, const char* what) :
     MemorySegmentOpenError(const char* file, size_t line, const char* what) :
         isc::Exception(file, line, what) {}
         isc::Exception(file, line, what) {}
 };
 };
 
 
+/// \brief Exception that is thrown when allocating a space in a MemorySegment
+/// results in growing the underlying segment.
+///
+/// See MemorySegment::allocate() for details.
 class MemorySegmentGrown : public Exception {
 class MemorySegmentGrown : public Exception {
 public:
 public:
     MemorySegmentGrown(const char* file, size_t line, const char* what) :
     MemorySegmentGrown(const char* file, size_t line, const char* what) :
         isc::Exception(file, line, what) {}
         isc::Exception(file, line, what) {}
 };
 };
 
 
+/// \brief General error that can be thrown by a MemorySegment
+/// implementation.
 class MemorySegmentError : public Exception {
 class MemorySegmentError : public Exception {
 public:
 public:
     MemorySegmentError(const char* file, size_t line, const char* what) :
     MemorySegmentError(const char* file, size_t line, const char* what) :
@@ -46,6 +54,10 @@ public:
 /// segments. This is an abstract class and a real
 /// segments. This is an abstract class and a real
 /// implementation such as MemorySegmentLocal should be used
 /// implementation such as MemorySegmentLocal should be used
 /// in code.
 /// in code.
+///
+/// It's intended to provide a unified interface whether the underlying
+/// memory is local to a specific process or is sharable by multiple
+/// processes.
 class MemorySegment {
 class MemorySegment {
 public:
 public:
     /// \brief Destructor
     /// \brief Destructor
@@ -97,7 +109,8 @@ public:
 
 
     /// \brief Check if all allocated memory was deallocated.
     /// \brief Check if all allocated memory was deallocated.
     ///
     ///
-    /// \return Returns <code>true</code> if all allocated memory was
+    /// \return Returns <code>true</code> if all allocated memory (including
+    /// names associated by memory addresses by \c setNamedAddress()) was
     /// deallocated, <code>false</code> otherwise.
     /// deallocated, <code>false</code> otherwise.
     virtual bool allMemoryDeallocated() const = 0;
     virtual bool allMemoryDeallocated() const = 0;
 
 

+ 14 - 0
src/lib/util/memory_segment_local.h

@@ -66,8 +66,22 @@ public:
     /// deallocated, <code>false</code> otherwise.
     /// deallocated, <code>false</code> otherwise.
     virtual bool allMemoryDeallocated() const;
     virtual bool allMemoryDeallocated() const;
 
 
+    /// \brief Local segment version of getNamedAddress.
+    ///
+    /// There's a small chance this method could throw std::bad_alloc.
+    /// It should be considered a fatal error.
     virtual void* getNamedAddress(const char* name);
     virtual void* getNamedAddress(const char* name);
+
+    /// \brief Local segment version of setNamedAddress.
+    ///
+    /// This version does not validate the given address to see whether it
+    /// belongs to this segment.
     virtual bool setNamedAddress(const char* name, void* addr);
     virtual bool setNamedAddress(const char* name, void* addr);
+
+    /// \brief Local segment version of clearNamedAddress.
+    ///
+    /// There's a small chance this method could throw std::bad_alloc.
+    /// It should be considered a fatal error.
     virtual bool clearNamedAddress(const char* name);
     virtual bool clearNamedAddress(const char* name);
 
 
 private:
 private:

+ 56 - 4
src/lib/util/memory_segment_mapped.h

@@ -25,17 +25,69 @@
 namespace isc {
 namespace isc {
 namespace util {
 namespace util {
 
 
-/// \brief TBD
+/// \brief Mapped-file based Memory Segment class.
+///
+/// This implementation of \c MemorySegment uses a concrete file to be mapped
+/// into memory.  Multiple processes can share the same mapped memory image.
+///
+/// This class provides two operation modes: read-only and read-write.
+/// A \c MemorySegmentMapped object in the read-only mode cannot modify the
+/// mapped memory image or other internal maintenance data of the object;
+/// In the read-write mode the object can allocate or deallocate memory
+/// from the mapped image, and the owner process can change the content.
+///
+/// This class does not provide any synchronization mechanism between
+/// read-only and read-write objects that share the same mapped image;
+/// in fact, the expected usage is the application (or a system of related
+/// processes) ensures there's at most one read-write object and if there's
+/// such an object no read-only object shares the image.  If an application
+/// uses this class beyond that expectation, it's the application's
+/// responsibility to provide necessary synchronization between the processes.
 class MemorySegmentMapped : boost::noncopyable, public MemorySegment {
 class MemorySegmentMapped : boost::noncopyable, public MemorySegment {
 public:
 public:
-    /// arbitrary choice.
+    /// \brief The default value of the mapped file size when newly created.
+    ///
+    /// Its value, 32KB, is an arbitrary choice, but considered to be
+    /// sufficiently but not too large.
     static const size_t INITIAL_SIZE = 32768;
     static const size_t INITIAL_SIZE = 32768;
 
 
-    /// \brief Constructor in the read-only mode
+    /// \brief Constructor in the read-only mode.
+    ///
+    /// This constructor will map the content of the given file into memory
+    /// in the "read only" mode; the resulting memory segment object cannot
+    /// be used with methods that would requite the mapped memory (see method
+    /// descriptions).  Also, if the application tries to modify memory in
+    /// the segment, it will make the application crash.
+    ///
+    /// The file must have been created by the other version of the
+    /// constructor beforehand and must be readable for the process
+    /// constructing this object.  Otherwise \c MemorySegmentOpenError
+    /// exception will be thrown.
+    ///
+    /// \throw MemorySegmentOpenError The given file does not exist, is not
+    /// readable, or not valid mappable segment.
+    /// \throw std::bad_alloc (rare case) internal resource allocation
+    /// failure.
     ///
     ///
-    /// Creates a local memory segment object
+    /// \param filename The file name to be mapped to memory.
     MemorySegmentMapped(const std::string& filename);
     MemorySegmentMapped(const std::string& filename);
 
 
+    /// \brief Constructor in the read-write mode.
+    ///
+    /// This is similar to the read-only version of the constructor, but
+    /// does not have the restrictions that the read-only version has.
+    /// If \c create is true and the specified file does not exist, it tries
+    /// to create a new file of the name and build internal data on it so that
+    /// the file will be mappable by this class object.  If \c create is
+    /// false, the specified file must exist and be writable, and have been
+    /// previously initialized by this version of constructor with \c create
+    /// being true.  If any of these conditions is not met,
+    /// \c MemorySegmentOpenError exception will be thrown.
+    ///
+    /// \param filename The file name to be mapped to memory.
+    /// \param create If true and the file does not exist a new one is created.
+    /// \param initial_size Specifies the size of the newly created file;
+    /// ignored if \c create is false.
     MemorySegmentMapped(const std::string& filename, bool create,
     MemorySegmentMapped(const std::string& filename, bool create,
                         size_t initial_size = INITIAL_SIZE);
                         size_t initial_size = INITIAL_SIZE);
 
 

+ 15 - 0
src/lib/util/tests/memory_segment_mapped_unittest.cc

@@ -28,6 +28,8 @@
 #include <cstring>
 #include <cstring>
 #include <limits>
 #include <limits>
 #include <stdexcept>
 #include <stdexcept>
+#include <fstream>
+#include <string>
 
 
 using namespace isc::util;
 using namespace isc::util;
 using boost::scoped_ptr;
 using boost::scoped_ptr;
@@ -112,6 +114,19 @@ TEST_F(MemorySegmentMappedTest, openFail) {
     EXPECT_THROW(MemorySegmentMapped(TEST_DATA_BUILDDIR "/nosuchfile.mapped",
     EXPECT_THROW(MemorySegmentMapped(TEST_DATA_BUILDDIR "/nosuchfile.mapped",
                                      false),
                                      false),
                  MemorySegmentOpenError);
                  MemorySegmentOpenError);
+
+    // Close the segment, break the file with bogus data, and try to reopen.
+    // It should fail with exception whether in the read-only or read-write,
+    // or "create if not exist" mode.
+    segment_.reset();
+    std::ofstream ofs(mapped_file, std::ios::trunc);
+    ofs << std::string(1024, 'x');
+    ofs.close();
+    EXPECT_THROW(MemorySegmentMapped sgmt(mapped_file), MemorySegmentOpenError);
+    EXPECT_THROW(MemorySegmentMapped sgmt(mapped_file, false),
+                 MemorySegmentOpenError);
+    EXPECT_THROW(MemorySegmentMapped sgmt(mapped_file, true),
+                 MemorySegmentOpenError);
 }
 }
 
 
 TEST_F(MemorySegmentMappedTest, allocate) {
 TEST_F(MemorySegmentMappedTest, allocate) {