summaryrefslogtreecommitdiffstats
path: root/src/rgw/driver/rados/rgw_sync_trace.h
blob: 1fcc8bed83012f0bf0c5d06bfa2564718af542e7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab ft=cpp

#pragma once

#include <atomic>

#include "common/ceph_mutex.h"
#include "common/shunique_lock.h"
#include "common/admin_socket.h"

#include <set>
#include <ostream>
#include <string>
#include <shared_mutex>
#include <boost/circular_buffer.hpp>

#define SSTR(o) ({      \
  std::stringstream ss; \
  ss << o;              \
  ss.str();             \
})

#define RGW_SNS_FLAG_ACTIVE   1
#define RGW_SNS_FLAG_ERROR    2

class RGWRados;
class RGWSyncTraceManager;
class RGWSyncTraceNode;
class RGWSyncTraceServiceMapThread;

using RGWSyncTraceNodeRef = std::shared_ptr<RGWSyncTraceNode>;

class RGWSyncTraceNode final {
  friend class RGWSyncTraceManager;

  CephContext *cct;
  RGWSyncTraceNodeRef parent;

  uint16_t state{0};
  std::string status;

  ceph::mutex lock = ceph::make_mutex("RGWSyncTraceNode::lock");

  std::string type;
  std::string id;

  std::string prefix;

  std::string resource_name;

  uint64_t handle;

  boost::circular_buffer<std::string> history;

  // private constructor, create with RGWSyncTraceManager::add_node()
  RGWSyncTraceNode(CephContext *_cct, uint64_t _handle,
                   const RGWSyncTraceNodeRef& _parent,
                   const std::string& _type, const std::string& _id);

 public:
  void set_resource_name(const std::string& s) {
    resource_name = s;
  }

  const std::string& get_resource_name() {
    return resource_name;
  }

  void set_flag(uint16_t s) {
    state |= s;
  }
  void unset_flag(uint16_t s) {
    state &= ~s;
  }
  bool test_flags(uint16_t f) {
    return (state & f) == f;
  }
  void log(int level, const std::string& s);

  std::string to_str() {
    return prefix + " " + status;
  }

  const std::string& get_prefix() {
    return prefix;
  }

  std::ostream& operator<<(std::ostream& os) { 
    os << to_str();
    return os;            
  }

  boost::circular_buffer<std::string>& get_history() {
    return history;
  }

  bool match(const std::string& search_term, bool search_history);
};

class RGWSyncTraceManager : public AdminSocketHook {
  friend class RGWSyncTraceNode;

  mutable std::shared_timed_mutex lock;
  using shunique_lock = ceph::shunique_lock<decltype(lock)>;

  CephContext *cct;
  RGWSyncTraceServiceMapThread *service_map_thread{nullptr};

  std::map<uint64_t, RGWSyncTraceNodeRef> nodes;
  boost::circular_buffer<RGWSyncTraceNodeRef> complete_nodes;

  std::atomic<uint64_t> count = { 0 };

  std::list<std::array<std::string, 3> > admin_commands;

  uint64_t alloc_handle() {
    return ++count;
  }
  void finish_node(RGWSyncTraceNode *node);

public:
  RGWSyncTraceManager(CephContext *_cct, int max_lru) : cct(_cct), complete_nodes(max_lru) {}
  ~RGWSyncTraceManager();

  void init(RGWRados *store);

  const RGWSyncTraceNodeRef root_node;

  RGWSyncTraceNodeRef add_node(const RGWSyncTraceNodeRef& parent,
                               const std::string& type,
                               const std::string& id = "");

  int hook_to_admin_command();
  int call(std::string_view command, const cmdmap_t& cmdmap,
	   const bufferlist&,
	   Formatter *f,
	   std::ostream& ss,
	   bufferlist& out) override;
  std::string get_active_names();
};