]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
os/bluestore: Add improved printer for Blob
authorAdam Kupczyk <akupczyk@ibm.com>
Wed, 18 Oct 2023 12:10:22 +0000 (12:10 +0000)
committerAdam Kupczyk <akupczyk@ibm.com>
Wed, 7 Aug 2024 10:47:50 +0000 (10:47 +0000)
Introduce printer class that allows to select parts of Blob that are to be printed.
It severly reduced amount of clutter in output.
Usage:
using P = Bluestore::Blob::printer;
dout << blob->printer(P::ptr + P::sdisk + P::schk);

Signed-off-by: Adam Kupczyk <akupczyk@ibm.com>
src/os/CMakeLists.txt
src/os/bluestore/BlueStore.h
src/os/bluestore/BlueStore_debug.cc [new file with mode: 0644]

index 67770933a3d86d0a85adb2dda458c1af3c368352..9353ceaa63fc861ebddba5bdaca41db19216188a 100644 (file)
@@ -15,6 +15,7 @@ if(WITH_BLUESTORE)
     bluestore/bluefs_types.cc
     bluestore/BlueRocksEnv.cc
     bluestore/BlueStore.cc
+    bluestore/BlueStore_debug.cc
     bluestore/simple_bitmap.cc
     bluestore/bluestore_types.cc
     bluestore/fastbmap_allocator_impl.cc
index 8141a7babf7c1b458079c98415e01faede025c4d..86961bc1af080fc6379dbfc870798d15eaecc2a5 100644 (file)
@@ -637,7 +637,24 @@ public:
 
     void dump(ceph::Formatter* f) const;
     friend std::ostream& operator<<(std::ostream& out, const Blob &b);
-
+    struct printer {
+      const Blob& blob;
+      uint8_t mode;
+      printer(const Blob& blob, uint8_t mode)
+      :blob(blob), mode(mode) {}
+      static constexpr uint8_t ptr = 1;    //pointer to Blob
+      static constexpr uint8_t nick = 2;   //a nickname of this Blob
+      static constexpr uint8_t disk = 4;   //disk allocations of Blob
+      static constexpr uint8_t sdisk = 8;  //shortened version of disk allocaitons
+      static constexpr uint8_t use = 16;   //use tracker
+      static constexpr uint8_t suse = 32;  //shortened use tracker
+      static constexpr uint8_t chk = 64;   //checksum, full dump
+      static constexpr uint8_t schk = 128; //only base checksum info
+    };
+    friend std::ostream& operator<<(std::ostream& out, const printer &p);
+    printer print(uint8_t mode) const {
+      return printer(*this, mode);
+    }
     const bluestore_blob_use_tracker_t& get_blob_use_tracker() const {
       return used_in_blob;
     }
diff --git a/src/os/bluestore/BlueStore_debug.cc b/src/os/bluestore/BlueStore_debug.cc
new file mode 100644 (file)
index 0000000..77bc04d
--- /dev/null
@@ -0,0 +1,216 @@
+// -*- 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) 2023 IBM
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation.  See file COPYING.
+ *
+ */
+#include <cstdint>
+#include <ostream>
+#include "BlueStore.h"
+
+static const std::string transition_table[26] = {
+"bcdfghjklmnprstuvxyz", //a
+"aeiloruy",//b
+"aeiloruvy",//c
+"aeilmnoruvy",//d
+"bcdfghjklmnprstvxz",//e
+
+"ailou",//f
+"aeilnoru",//g
+"aeiloru",//h
+"dfghklmnpqrstvwx",//i
+"aeiou",//j
+
+"aeiloru",//k
+"aeimnou",//l
+"aeinotuy",//m
+"aeiou",//n
+"bcdfghjklmnpqrstvwxz",//o
+"aehiloruy",//p
+
+"aeiloru",//q
+"adefiklmnotuvy",//r
+"aehiklmnopqrtuvwy",//s
+"acefhiklmnorsuvwy",//t
+"bcdfghklmnpqrsvwxyz",//u
+
+"acdeiklmorsu",//v
+"aehilnorstu",//w
+"aeilnorstuy",//x
+"aehinorsuxz",//y
+"aeiouy" //z
+};
+
+std::string int_to_fancy_name(uint64_t x)
+{
+  std::string result;
+  uint8_t c = x % 26;
+  x = x / 26;
+  result.push_back(c+'a');
+  while (x > 0) {
+    uint8_t range = transition_table[c].length();
+    uint8_t p = x % range;
+    c = transition_table[c][p] - 'a';
+    x = x / range;
+    result.push_back(c+'a');
+  }
+  return result;
+}
+
+// Use special printing for multiplies of 1024; print K suffix
+struct maybe_K {
+  uint32_t x;
+  maybe_K(uint32_t x) : x(x) {}
+};
+std::ostream &operator<<(std::ostream &out, const maybe_K &k) {
+  if (((k.x & 0x3ff) == 0) && (k.x != 0)) {
+    if (k.x != 0x400)
+      out << (k.x / 0x400);
+    out << "K";
+  } else {
+    out << std::hex << k.x << std::dec;
+  }
+  return out;
+}
+
+std::ostream& operator<<(std::ostream& out, const BlueStore::Blob::printer &p)
+{
+  using P = BlueStore::Blob::printer;
+  out << "Blob(";
+  if (p.mode & P::ptr) {
+    out << &p.blob << " ";
+  }
+  if (p.mode & P::nick) {
+    uint64_t v = uint64_t(&p.blob);
+    v = (v - 0x555550000000) / 16;
+    out << int_to_fancy_name(v) << " ";
+  }
+  const bluestore_blob_t& bblob = p.blob.get_blob();
+  if (p.mode & P::disk) {
+    //use default printer for std::vector * bluestore_pextent_t
+    out << "disk=" << bblob.get_extents() << " ";
+  }
+  if (p.mode & P::sdisk) {
+    const PExtentVector& ev = bblob.get_extents();
+    uint64_t bits = 0;
+    for (auto i : ev) {
+      if (i.is_valid()) bits |= i.offset;
+      bits |= i.length;
+    }
+    uint32_t zeros = 0; //zeros to apply to all values
+    while ((bits & 0xf) == 0) {
+      bits = bits >> 4;
+      ++zeros;
+    }
+    out << "disk=0x[" << std::hex;
+    for (size_t i = 0; i < ev.size(); ++i) {
+      if (i != 0) {
+        out << ",";
+      }
+      if (ev[i].is_valid()) {
+        out << (ev[i].offset >> zeros * 4) << "~";
+      } else {
+        out << "!";
+      }
+      out << (ev[i].length >> zeros * 4);
+    }
+    out << "]" << std::dec;
+    while (zeros > 0) {
+      out << "0";
+      --zeros;
+    }
+    out << " ";
+  }
+  //always print lengths, if not printing use tracker
+  if (!(p.mode & (P::use | P::suse)) || bblob.is_compressed()) {
+    // Need to print blob logical length, no tracker printing
+    // + there is no real tracker for compressed blobs
+    if (bblob.is_compressed()) {
+      out << "len=" << std::hex << bblob.get_logical_length() << "->"
+          << bblob.get_compressed_payload_length() << " " << std::dec;
+    } else {
+      out << "len=" << std::hex << bblob.get_logical_length() << std::dec << " ";
+    }
+  }
+  if ((p.mode & P::use) && !bblob.is_compressed()) {
+    out << p.blob.get_blob_use_tracker() << " ";
+  }
+  if (p.mode & P::suse) {
+    auto& tracker = p.blob.get_blob_use_tracker();
+    if (bblob.is_compressed()) {
+      out << "[" << std::hex << tracker.get_referenced_bytes() << std::dec << "] ";
+    } else {
+      const uint32_t* au_array = tracker.get_au_array();
+      uint16_t zeros = 0;
+      uint16_t full = 0;
+      uint16_t num_au = tracker.get_num_au();
+      uint32_t au_size = tracker.au_size;
+      uint32_t def = std::numeric_limits<uint32_t>::max();
+      out << "track=" << tracker.get_num_au() << "*" << maybe_K(tracker.au_size);
+      for (size_t i = 0; i < num_au; i++) {
+        if (au_array[i] == 0) ++zeros;
+        if (au_array[i] == au_size) ++full;
+      }
+      if (zeros >= num_au - 3 && num_au > 6) def = 0;
+      if (full >= num_au - 3 && num_au > 6) def = au_size;
+      if (def != std::numeric_limits<uint32_t>::max()) {
+        out << "{" << maybe_K(def) << "}[";
+        for (size_t i = 0; i < num_au; i++) {
+          if (au_array[i] != def) {
+            out << i << "=" << maybe_K(au_array[i]);
+            ++i;
+            for (; i < num_au; i++) {
+              if (au_array[i] != def) {
+                out << "," << i << "=" << maybe_K(au_array[i]);
+              }
+            }
+          }
+        }
+        out << "] ";
+      } else {
+        out << "[";
+        for (size_t i = 0; i < num_au; i++) {
+          if (i != 0) out << ",";
+          out << maybe_K(au_array[i]);
+        }
+        out << "] ";
+      }
+    }
+  }
+  if (bblob.has_csum()) {
+    if (p.mode & (P::schk | P::chk)) {
+      out << Checksummer::get_csum_type_string(bblob.csum_type) << "/"
+          << (int)bblob.csum_chunk_order << "/" << bblob.csum_data.length();
+    }
+    if (p.mode & P::chk) {
+      std::vector<uint64_t> v;
+      unsigned n = bblob.get_csum_count();
+      for (unsigned i = 0; i < n; ++i)
+        v.push_back(bblob.get_csum_item(i));
+      out << std::hex << v << std::dec;
+    }
+    if (p.mode & (P::schk | P::chk)) {
+      out << " ";
+    }
+  }
+  if (p.blob.is_spanning()) {
+    out << " spanning.id=" << p.blob.id;
+  }
+  if (p.blob.shared_blob) {
+    if (p.blob.shared_blob->get_sbid() != 0) {
+      out << " " << *p.blob.shared_blob;
+    }
+  } else {
+    out << " (shared_blob=NULL)";
+  }
+  out << ")";
+  return out;
+}
+