This is a precalculated table of all pg mappings.
Signed-off-by: Sage Weil <sage@redhat.com>
msg/msg_types.cc
common/hobject.cc
osd/OSDMap.cc
+ osd/OSDMapMapping.cc
common/histogram.cc
osd/osd_types.cc
osd/OpRequest.cc
#include "include/memory.h"
using namespace std;
-//forward declaration
+// forward declaration
class CephContext;
class CrushWrapper;
+
+
/*
* we track up to two intervals during which the osd was alive and
* healthy. the most recent is [up_from,up_thru), where up_thru is
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "OSDMapMapping.h"
+#include "OSDMap.h"
+
+// ensure that we have a PoolMappings for each pool and that
+// the dimensions (pg_num and size) match up.
+void OSDMapMapping::_init_mappings(const OSDMap& osdmap)
+{
+ auto q = pools.begin();
+ for (auto& p : osdmap.get_pools()) {
+ // drop unneeded pools
+ while (q != pools.end() && q->first < p.first) {
+ q = pools.erase(q);
+ }
+ if (q != pools.end() && q->first == p.first) {
+ if (q->second.pg_num != p.second.get_pg_num() ||
+ q->second.size != p.second.get_size()) {
+ // pg_num changed
+ q = pools.erase(q);
+ } else {
+ // keep it
+ ++q;
+ continue;
+ }
+ }
+ pools.emplace(p.first, PoolMapping(p.second.get_size(),
+ p.second.get_pg_num()));
+ }
+ pools.erase(q, pools.end());
+ assert(pools.size() == osdmap.get_pools().size());
+}
+
+void OSDMapMapping::update(const OSDMap& osdmap)
+{
+ _init_mappings(osdmap);
+ for (auto& p : osdmap.get_pools()) {
+ _update_range(osdmap, p.first, 0, p.second.get_pg_num());
+ }
+ _build_rmap(osdmap);
+ //_dump(); // for debugging
+}
+
+void OSDMapMapping::_build_rmap(const OSDMap& osdmap)
+{
+ acting_rmap.resize(osdmap.get_max_osd());
+ up_rmap.resize(osdmap.get_max_osd());
+ for (auto& v : acting_rmap) {
+ v.resize(0);
+ }
+ for (auto& v : up_rmap) {
+ v.resize(0);
+ }
+ for (auto& p : pools) {
+ pg_t pgid(0, p.first);
+ for (unsigned ps = 0; ps < p.second.pg_num; ++ps) {
+ pgid.set_ps(ps);
+ int32_t *row = &p.second.table[p.second.row_size() * ps];
+ for (int i = 0; i < row[2]; ++i) {
+ if (row[4 + i] != CRUSH_ITEM_NONE) {
+ acting_rmap[row[4 + i]].push_back(pgid);
+ }
+ }
+ for (int i = 0; i < row[3]; ++i) {
+ up_rmap[row[4 + p.second.size + i]].push_back(pgid);
+ }
+ }
+ }
+}
+
+void OSDMapMapping::_dump()
+{
+ for (auto& p : pools) {
+ cout << "pool " << p.first << std::endl;
+ for (unsigned i = 0; i < p.second.table.size(); ++i) {
+ cout << " " << p.second.table[i];
+ if (i % p.second.row_size() == p.second.row_size() - 1)
+ cout << std::endl;
+ }
+ }
+}
+
+void OSDMapMapping::_update_range(
+ const OSDMap& osdmap,
+ int64_t pool,
+ unsigned pg_begin,
+ unsigned pg_end)
+{
+ auto i = pools.find(pool);
+ assert(i != pools.end());
+ assert(pg_begin <= pg_end);
+ assert(pg_end <= i->second.pg_num);
+ for (unsigned ps = pg_begin; ps < pg_end; ++ps) {
+ vector<int> up, acting;
+ int up_primary, acting_primary;
+ osdmap.pg_to_up_acting_osds(
+ pg_t(ps, pool),
+ &up, &up_primary, &acting, &acting_primary);
+ i->second.set(ps, std::move(up), up_primary,
+ std::move(acting), acting_primary);
+ }
+}
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+
+#ifndef CEPH_OSDMAPMAPPING_H
+#define CEPH_OSDMAPMAPPING_H
+
+#include <vector>
+#include <map>
+
+#include "osd/osd_types.h"
+
+class OSDMap;
+
+/// a precalculated mapping of every PG for a given OSDMap
+class OSDMapMapping {
+ struct PoolMapping {
+ unsigned size = 0;
+ unsigned pg_num = 0;
+ std::vector<int32_t> table;
+
+ size_t row_size() const {
+ return
+ 1 + // acting_primary
+ 1 + // up_primary
+ 1 + // num acting
+ 1 + // num up
+ size + // acting
+ size; // up
+ }
+
+ PoolMapping(int s, int p)
+ : size(s),
+ pg_num(p),
+ table(pg_num * row_size()) {
+ }
+
+ void get(size_t ps,
+ std::vector<int> *up,
+ int *up_primary,
+ std::vector<int> *acting,
+ int *acting_primary) {
+ int32_t *row = &table[row_size() * ps];
+ if (acting_primary) {
+ *acting_primary = row[0];
+ }
+ if (up_primary) {
+ *up_primary = row[1];
+ }
+ if (acting) {
+ acting->resize(row[2]);
+ for (int i = 0; i < row[2]; ++i) {
+ (*acting)[i] = row[4 + i];
+ }
+ }
+ if (up) {
+ up->resize(row[3]);
+ for (int i = 0; i < row[3]; ++i) {
+ (*up)[i] = row[4 + size + i];
+ }
+ }
+ }
+
+ void set(size_t ps,
+ const std::vector<int>& up,
+ int up_primary,
+ const std::vector<int>& acting,
+ int acting_primary) {
+ int32_t *row = &table[row_size() * ps];
+ row[0] = acting_primary;
+ row[1] = up_primary;
+ row[2] = acting.size();
+ row[3] = up.size();
+ for (int i = 0; i < row[2]; ++i) {
+ row[4 + i] = acting[i];
+ }
+ for (int i = 0; i < row[3]; ++i) {
+ row[4 + size + i] = up[i];
+ }
+ }
+ };
+
+ std::map<int64_t,PoolMapping> pools;
+ std::vector<std::vector<pg_t>> acting_rmap; // osd -> pg
+ std::vector<std::vector<pg_t>> up_rmap; // osd -> pg
+
+ void _init_mappings(const OSDMap& osdmap);
+ void _update_range(
+ const OSDMap& map,
+ int64_t pool,
+ unsigned pg_begin, unsigned pg_end);
+
+ void _build_rmap(const OSDMap& osdmap);
+
+ void _dump();
+
+public:
+ void get(pg_t pgid,
+ std::vector<int> *up,
+ int *up_primary,
+ std::vector<int> *acting,
+ int *acting_primary) {
+ auto p = pools.find(pgid.pool());
+ assert(p != pools.end());
+ p->second.get(pgid.ps(), up, up_primary, acting, acting_primary);
+ }
+
+ const std::vector<pg_t>& get_osd_acting_pgs(unsigned osd) {
+ assert(osd < acting_rmap.size());
+ return acting_rmap[osd];
+ }
+ const std::vector<pg_t>& get_osd_up_pgs(unsigned osd) {
+ assert(osd < up_rmap.size());
+ return up_rmap[osd];
+ }
+
+ void update(const OSDMap& map);
+};
+
+
+#endif
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
#include "gtest/gtest.h"
#include "osd/OSDMap.h"
+#include "osd/OSDMapMapping.h"
#include "global/global_context.h"
#include "global/global_init.h"
const static int num_osds = 6;
public:
OSDMap osdmap;
+ OSDMapMapping mapping;
+
OSDMapTest() {}
void set_up_map() {
vector<int> *any,
vector<int> *first,
vector<int> *primary) {
+ mapping.update(osdmap);
for (int i=0; i<num; ++i) {
- vector<int> o;
- int p;
+ vector<int> up, acting;
+ int up_primary, acting_primary;
pg_t pgid(i, pool);
- osdmap.pg_to_acting_osds(pgid, &o, &p);
- for (unsigned j=0; j<o.size(); ++j)
- (*any)[o[j]]++;
- if (!o.empty())
- (*first)[o[0]]++;
- if (p >= 0)
- (*primary)[p]++;
+ osdmap.pg_to_up_acting_osds(pgid,
+ &up, &up_primary, &acting, &acting_primary);
+ for (unsigned j=0; j<acting.size(); ++j)
+ (*any)[acting[j]]++;
+ if (!acting.empty())
+ (*first)[acting[0]]++;
+ if (acting_primary >= 0)
+ (*primary)[acting_primary]++;
+
+ // compare to precalc mapping
+ vector<int> up2, acting2;
+ int up_primary2, acting_primary2;
+ pgid = osdmap.raw_pg_to_pg(pgid);
+ mapping.get(pgid, &up2, &up_primary2, &acting2, &acting_primary2);
+ ASSERT_EQ(up, up2);
+ ASSERT_EQ(up_primary, up_primary2);
+ ASSERT_EQ(acting, acting2);
+ ASSERT_EQ(acting_primary, acting_primary2);
}
}
};