]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
monitorstore: implement put_bl_sn_map
authorSage Weil <sage@newdream.net>
Fri, 19 Aug 2011 16:46:14 +0000 (09:46 -0700)
committerSage Weil <sage@newdream.net>
Fri, 19 Aug 2011 16:53:57 +0000 (09:53 -0700)
This will commit a big batch of values safely.  We push it down into
MonitorStore so we can avoid an fsync(2) per file.

Signed-off-by: Sage Weil <sage@newdream.net>
src/mon/MonitorStore.cc
src/mon/MonitorStore.h

index d3838015cb620b1cfd1b53e6dd22f3c84c04d814..56596773ace156a09fbbbe063ea02d6d7c770a5b 100644 (file)
@@ -340,3 +340,76 @@ int MonitorStore::write_bl_ss(bufferlist& bl, const char *a, const char *b, bool
   assert(!err);  // for now
   return 0;
 }
+
+int MonitorStore::put_bl_sn_map(const char *a, map<version_t,bufferlist>& vals)
+{
+  version_t first = vals.begin()->first;
+  version_t last = vals.rbegin()->first;
+  dout(15) <<  "put_bl_sn_map " << a << "/[" << first << ".." << last << "]" << dendl;
+
+  // only do a big sync if there are several values.
+  if (vals.size() < 5) {
+    // just do them individually
+    for (map<version_t,bufferlist>::iterator p = vals.begin();
+        p != vals.end();
+        p++) {
+      int err = put_bl_sn(p->second, a, p->first);
+      if (err < 0)
+       return err;
+    }
+    return 0;
+  }
+
+  // make sure dir exists
+  char dfn[1024];
+  snprintf(dfn, sizeof(dfn), "%s/%s", dir.c_str(), a);
+  ::mkdir(dfn, 0755);
+
+  for (map<version_t,bufferlist>::iterator p = vals.begin();
+       p != vals.end();
+       p++) {
+    char tfn[1024], fn[1024];
+
+    snprintf(fn, sizeof(fn), "%s/%llu", dfn, (long long unsigned)p->first);
+    snprintf(tfn, sizeof(tfn), "%s.new", fn);
+
+    int fd = ::open(tfn, O_WRONLY|O_CREAT, 0644);
+    if (fd < 0) {
+      int err = -errno;
+      derr << "failed to open " << tfn << ": " << cpp_strerror(err) << dendl;
+      return err;
+    }
+
+    int err = p->second.write_fd(fd);
+    ::close(fd);
+    if (err < 0)
+      return -errno;
+  }
+
+  // sync them all
+  int dirfd = ::open(dir.c_str(), O_RDONLY);
+  sync_filesystem(dirfd);
+  ::close(dirfd);
+    
+  // rename them all into place
+  for (map<version_t,bufferlist>::iterator p = vals.begin();
+       p != vals.end();
+       p++) {
+    char tfn[1024], fn[1024];
+    
+    snprintf(fn, sizeof(fn), "%s/%llu", dfn, (long long unsigned)p->first);
+    snprintf(tfn, sizeof(tfn), "%s.new", fn);
+    
+    int err = ::rename(tfn, fn);
+    if (err < 0)
+      return -errno;
+  }
+    
+  // fsync the dir (to commit the renames)
+  dirfd = ::open(dir.c_str(), O_RDONLY);
+  ::fsync(dirfd);
+  ::close(dirfd);
+
+  return 0;
+}
+
index 8e931e19e079407e57bfe35675e2d0f695673cbd..13d67ff7f8a0ba7d921cfd2c4e4e42dad2e1eb12 100644 (file)
@@ -68,6 +68,14 @@ public:
     snprintf(bs, sizeof(bs), "%llu", (unsigned long long)b);
     return put_bl_ss(bl, a, bs, sync);
   }
+  /**
+   * Put a whole set of values efficiently and safely.
+   *
+   * @param a - prefix/directory
+   * @param vals - map of int name -> values
+   * @return 0 for success or negative error code
+   */
+  int put_bl_sn_map(const char *a, map<version_t,bufferlist>& vals);
 
   int erase_ss(const char *a, const char *b);
   int erase_sn(const char *a, version_t b) {