[PATCH 2/9] Add "fake" shared memory segment implementation.

From: Dmitry Kurochkin <dmitry.kurochkin_at_measurement-factory.com>
Date: Thu, 29 Sep 2011 03:06:00 +0400

"Fake" shared memory segments are enabled #if a system does not
support POSIX shared memory. Such segments use regular new to
allocate memory, it is not shared among multiple processes. The
purpose of the change is to allow code that uses Ipc::Mem::Segment to
run in non-SMP mode (that is when only a single process, except for
master, is running) on systems without POSIX shared memory support.

Note: running SHM-using features in SMP mode still requires POSIX
shared memory support, the patch does not change that.

---
 src/ipc/mem/Segment.cc |  110 +++++++++++++++++++++++++++++++++++++++--------
 src/ipc/mem/Segment.h  |   18 ++++++--
 2 files changed, 105 insertions(+), 23 deletions(-)
diff --git src/ipc/mem/Segment.cc src/ipc/mem/Segment.cc
index 98c393c..5702fd0 100644
--- src/ipc/mem/Segment.cc
+++ src/ipc/mem/Segment.cc
@@ -16,8 +16,24 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
+void *
+Ipc::Mem::Segment::reserve(size_t chunkSize)
+{
+    Must(theMem);
+    // check for overflows
+    // chunkSize >= 0 may result in warnings on systems where off_t is unsigned
+    assert(!chunkSize || static_cast<off_t>(chunkSize) > 0);
+    assert(static_cast<off_t>(chunkSize) <= theSize);
+    assert(theReserved <= theSize - static_cast<off_t>(chunkSize));
+    void *result = reinterpret_cast<char*>(theMem) + theReserved;
+    theReserved += chunkSize;
+    return result;
+}
+
+#if HAVE_SHM
+
 Ipc::Mem::Segment::Segment(const char *const id):
-        theName(GenerateName(id)), theFD(-1), theMem(NULL),
+        theFD(-1), theName(GenerateName(id)), theMem(NULL),
         theSize(0), theReserved(0), doUnlink(false)
 {
 }
@@ -33,14 +49,11 @@ Ipc::Mem::Segment::~Segment()
         unlink();
 }
 
+// fake Ipc::Mem::Segment::Enabled (!HAVE_SHM) is more selective
 bool
 Ipc::Mem::Segment::Enabled()
 {
-#if HAVE_SHM
     return true;
-#else
-    return false;
-#endif
 }
 
 void
@@ -135,20 +148,6 @@ Ipc::Mem::Segment::unlink()
         debugs(54, 3, HERE << "unlinked " << theName << " segment");
 }
 
-void *
-Ipc::Mem::Segment::reserve(size_t chunkSize)
-{
-    Must(theMem);
-    // check for overflows
-    // chunkSize >= 0 may result in warnings on systems where off_t is unsigned
-    assert(!chunkSize || static_cast<off_t>(chunkSize) > 0);
-    assert(static_cast<off_t>(chunkSize) <= theSize);
-    assert(theReserved <= theSize - static_cast<off_t>(chunkSize));
-    void *result = reinterpret_cast<char*>(theMem) + theReserved;
-    theReserved += chunkSize;
-    return result;
-}
-
 /// determines the size of the underlying "file"
 off_t
 Ipc::Mem::Segment::statSize(const char *context) const
@@ -184,3 +183,76 @@ Ipc::Mem::Segment::GenerateName(const char *id)
     name.append(id);
     return name;
 }
+
+#else // HAVE_SHM
+
+#include <map>
+
+typedef std::map<String, Ipc::Mem::Segment *> SegmentMap;
+static SegmentMap Segments;
+
+Ipc::Mem::Segment::Segment(const char *const id):
+    theName(id), theMem(NULL), theSize(0), theReserved(0), doUnlink(false)
+{
+}
+
+Ipc::Mem::Segment::~Segment()
+{
+    if (doUnlink) {
+        delete [] static_cast<char *>(theMem);
+        debugs(54, 3, HERE << "deleted " << theName << " segment");
+    }
+}
+
+bool
+Ipc::Mem::Segment::Enabled()
+{
+    return !InDaemonMode() || (!UsingSmp() && IamWorkerProcess());
+}
+
+void
+Ipc::Mem::Segment::create(const off_t aSize)
+{
+    assert(aSize > 0);
+    assert(!theMem);
+    checkSupport("Fake segment creation");
+
+    const bool inserted = Segments.insert(std::make_pair(theName, this)).second;
+    if (!inserted)
+        fatalf("Duplicate fake segment creation: %s", theName.termedBuf());
+
+    theMem = new char[aSize];
+    theSize = aSize;
+    doUnlink = true;
+
+    debugs(54, 3, HERE << "created " << theName << " fake segment: " << theSize);
+}
+
+void
+Ipc::Mem::Segment::open()
+{
+    assert(!theMem);
+    checkSupport("Fake segment open");
+
+    const SegmentMap::const_iterator i = Segments.find(theName);
+    if (i == Segments.end())
+        fatalf("Fake segment not found: %s", theName.termedBuf());
+
+    const Segment &segment = *i->second;
+    theMem = segment.theMem;
+    theSize = segment.theSize;
+
+    debugs(54, 3, HERE << "opened " << theName << " fake segment: " << theSize);
+}
+
+void
+Ipc::Mem::Segment::checkSupport(const char *const context)
+{
+    if (!Enabled()) {
+        debugs(54, 5, HERE << "True shared memory segments are not supported. "
+               "Cannot fake shared segments in SMP config.");
+        fatalf("%s failed", context);
+    }
+}
+
+#endif // HAVE_SHM
diff --git src/ipc/mem/Segment.h src/ipc/mem/Segment.h
index 138de2b..b82ac4f 100644
--- src/ipc/mem/Segment.h
+++ src/ipc/mem/Segment.h
@@ -36,6 +36,13 @@ public:
 
 
 private:
+
+    // not implemented
+    Segment(const Segment &);
+    Segment &operator =(const Segment &);
+
+#if HAVE_SHM
+
     void attach();
     void detach();
     void unlink(); ///< unlink the segment
@@ -43,12 +50,15 @@ private:
 
     static String GenerateName(const char *id);
 
-    // not implemented
-    Segment(const Segment &);
-    Segment &operator =(const Segment &);
+    int theFD; ///< shared memory segment file descriptor
+
+#else // HAVE_SHM
+
+    void checkSupport(const char *const context);
+
+#endif // HAVE_SHM
 
     const String theName; ///< shared memory segment file name
-    int theFD; ///< shared memory segment file descriptor
     void *theMem; ///< pointer to mmapped shared memory segment
     off_t theSize; ///< shared memory segment size
     off_t theReserved; ///< the total number of reserve()d bytes
-- 
1.7.6.3
Received on Wed Sep 28 2011 - 23:06:49 MDT

This archive was generated by hypermail 2.2.0 : Thu Sep 29 2011 - 12:00:03 MDT