]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
osd: implement pg_t::is_split()
authorSage Weil <sage@newdream.net>
Mon, 20 Feb 2012 23:59:00 +0000 (15:59 -0800)
committerSage Weil <sage@newdream.net>
Mon, 27 Feb 2012 19:44:24 +0000 (11:44 -0800)
Test to determine if a pg has split between two pool sizes, and if so,
what its children are.

Signed-off-by: Sage Weil <sage@newdream.net>
src/Makefile.am
src/osd/osd_types.cc
src/osd/osd_types.h
src/test/test_osd_types.cc [new file with mode: 0644]

index 0d573bccbc503386c402337222ad4f16264d5e29..491e07bb1084d2e6623e4ae249d51781684f3361 100644 (file)
@@ -501,6 +501,11 @@ unittest_ceph_argparse_LDADD = libglobal.la ${UNITTEST_LDADD}
 unittest_ceph_argparse_CXXFLAGS = ${AM_CXXFLAGS} ${UNITTEST_CXXFLAGS}
 check_PROGRAMS += unittest_ceph_argparse
 
+unittest_osd_types_SOURCES = test/test_osd_types.cc libcommon.la
+unittest_osd_types_CXXFLAGS = ${AM_CXXFLAGS} ${UNITTEST_CXXFLAGS}
+unittest_osd_types_LDADD = libglobal.la $(PTHREAD_LIBS) -lm ${UNITTEST_LDADD} $(CRYPTO_LIBS) $(EXTRALIBS)
+check_PROGRAMS += unittest_osd_types
+
 unittest_gather_SOURCES = test/gather.cc
 unittest_gather_LDADD = ${LIBGLOBAL_LDA} ${UNITTEST_LDADD}
 unittest_gather_CXXFLAGS = ${AM_CXXFLAGS} ${UNITTEST_CXXFLAGS}
index b97fe5b33e61cc9c1a16ffdf261f498b06350e5d..68f3cb45121f841069fa944e3f4da107b7a37fe7 100644 (file)
@@ -180,6 +180,40 @@ bool pg_t::parse(const char *s)
   return true;
 }
 
+bool pg_t::is_split(unsigned old_pg_num, unsigned new_pg_num, set<pg_t>& children) const
+{
+  assert(m_seed < old_pg_num);
+  if (new_pg_num <= old_pg_num)
+    return false;
+
+  if (true) {
+    int old_bits = pg_pool_t::calc_bits_of(old_pg_num);
+    int old_mask = (1 << old_bits) - 1;
+    for (int n = 1; ; n++) {
+      int next_bit = (n << (old_bits-1));
+      unsigned s = next_bit | m_seed;
+
+      if (s < old_pg_num || s == m_seed)
+       continue;
+      if (s >= new_pg_num)
+       break;
+      if ((unsigned)ceph_stable_mod(s, old_pg_num, old_mask) == m_seed)
+       children.insert(pg_t(s, m_pool, m_preferred));
+    }
+  }
+  if (false) {
+    // brute force
+    int old_bits = pg_pool_t::calc_bits_of(old_pg_num);
+    int old_mask = (1 << old_bits) - 1;
+    for (unsigned x = old_pg_num; x < new_pg_num; ++x) {
+      unsigned o = ceph_stable_mod(x, old_pg_num, old_mask);
+      if (o == m_seed)
+       children.insert(pg_t(x, m_pool, m_preferred));
+    }
+  }
+  return !children.empty();
+}
+
 void pg_t::dump(Formatter *f) const
 {
   f->dump_unsigned("pool", m_pool);
index 1d7d294deccbc3e41028f43df1715743b06c369d..281c60f0f3dcfdbddae192046a8841f3a5bc5e3d 100644 (file)
@@ -238,6 +238,8 @@ struct pg_t {
   int print(char *o, int maxlen) const;
   bool parse(const char *s);
 
+  bool is_split(unsigned old_pg_num, unsigned new_pg_num, set<pg_t>& children) const;
+
   void encode(bufferlist& bl) const {
     __u8 v = 1;
     ::encode(v, bl);
@@ -659,7 +661,7 @@ struct pg_pool_t {
   unsigned get_lpg_num_mask() const { return lpg_num_mask; }
   unsigned get_lpgp_num_mask() const { return lpgp_num_mask; }
 
-  int calc_bits_of(int t);
+  static int calc_bits_of(int t);
   void calc_pg_masks();
 
   /*
diff --git a/src/test/test_osd_types.cc b/src/test/test_osd_types.cc
new file mode 100644 (file)
index 0000000..910d822
--- /dev/null
@@ -0,0 +1,120 @@
+// -*- mode:C; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2011 New Dream Network
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License version 2, as published by the Free Software
+ * Foundation.  See file COPYING.
+ *
+ */
+
+#include "include/types.h"
+#include "osd/osd_types.h"
+#include "gtest/gtest.h"
+
+#include <sstream>
+
+
+TEST(pg_t, split)
+{
+  pg_t pgid(0, 0, -1);
+  set<pg_t> s;
+  bool b;
+
+  s.clear();
+  b = pgid.is_split(1, 1, s);
+  ASSERT_TRUE(!b);
+
+  s.clear();
+  b = pgid.is_split(2, 4, s);
+  ASSERT_TRUE(b);
+  ASSERT_EQ(1u, s.size());
+  ASSERT_TRUE(s.count(pg_t(2, 0, -1)));
+
+  s.clear();
+  b = pgid.is_split(2, 8, s);
+  ASSERT_TRUE(b);
+  ASSERT_EQ(3u, s.size());
+  ASSERT_TRUE(s.count(pg_t(2, 0, -1)));
+  ASSERT_TRUE(s.count(pg_t(4, 0, -1)));
+  ASSERT_TRUE(s.count(pg_t(6, 0, -1)));
+
+  s.clear();
+  b = pgid.is_split(3, 8, s);
+  ASSERT_TRUE(b);
+  ASSERT_EQ(1u, s.size());
+  ASSERT_TRUE(s.count(pg_t(4, 0, -1)));
+
+  s.clear();
+  b = pgid.is_split(6, 8, s);
+  ASSERT_TRUE(!b);
+  ASSERT_EQ(0u, s.size());
+
+  pgid = pg_t(1, 0, -1);
+  
+  s.clear();
+  b = pgid.is_split(2, 4, s);
+  ASSERT_TRUE(b);
+  ASSERT_EQ(1u, s.size());
+  ASSERT_TRUE(s.count(pg_t(3, 0, -1)));
+
+  s.clear();
+  b = pgid.is_split(2, 6, s);
+  ASSERT_TRUE(b);
+  ASSERT_EQ(2u, s.size());
+  ASSERT_TRUE(s.count(pg_t(3, 0, -1)));
+  ASSERT_TRUE(s.count(pg_t(5, 0, -1)));
+
+  s.clear();
+  b = pgid.is_split(2, 8, s);
+  ASSERT_TRUE(b);
+  ASSERT_EQ(3u, s.size());
+  ASSERT_TRUE(s.count(pg_t(3, 0, -1)));
+  ASSERT_TRUE(s.count(pg_t(5, 0, -1)));
+  ASSERT_TRUE(s.count(pg_t(7, 0, -1)));
+
+  s.clear();
+  b = pgid.is_split(4, 8, s);
+  ASSERT_TRUE(b);
+  ASSERT_EQ(1u, s.size());
+  ASSERT_TRUE(s.count(pg_t(5, 0, -1)));
+
+  s.clear();
+  b = pgid.is_split(3, 8, s);
+  ASSERT_TRUE(b);
+  ASSERT_EQ(3u, s.size());
+  ASSERT_TRUE(s.count(pg_t(3, 0, -1)));
+  ASSERT_TRUE(s.count(pg_t(5, 0, -1)));
+  ASSERT_TRUE(s.count(pg_t(7, 0, -1)));
+
+  s.clear();
+  b = pgid.is_split(6, 8, s);
+  ASSERT_TRUE(!b);
+  ASSERT_EQ(0u, s.size());
+
+  pgid = pg_t(3, 0, -1);
+
+  s.clear();
+  b = pgid.is_split(7, 8, s);
+  ASSERT_TRUE(b);
+  ASSERT_EQ(1u, s.size());
+  ASSERT_TRUE(s.count(pg_t(7, 0, -1)));
+
+  s.clear();
+  b = pgid.is_split(7, 12, s);
+  ASSERT_TRUE(b);
+  ASSERT_EQ(2u, s.size());
+  ASSERT_TRUE(s.count(pg_t(7, 0, -1)));
+  ASSERT_TRUE(s.count(pg_t(11, 0, -1)));
+
+  s.clear();
+  b = pgid.is_split(7, 11, s);
+  ASSERT_TRUE(b);
+  ASSERT_EQ(1u, s.size());
+  ASSERT_TRUE(s.count(pg_t(7, 0, -1)));
+
+}