]> git.proxmox.com Git - ceph.git/blob - ceph/src/mgr/PyFormatter.h
import 15.2.0 Octopus source
[ceph.git] / ceph / src / mgr / PyFormatter.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2015 Red Hat Inc
7 *
8 * Author: John Spray <john.spray@redhat.com>
9 *
10 * This is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License version 2.1, as published by the Free Software
13 * Foundation. See file COPYING.
14 *
15 */
16
17 #ifndef PY_FORMATTER_H_
18 #define PY_FORMATTER_H_
19
20 // Python.h comes first because otherwise it clobbers ceph's assert
21 #include <Python.h>
22
23 #include <stack>
24 #include <string>
25 #include <string_view>
26 #include <sstream>
27 #include <memory>
28 #include <list>
29
30 #include "common/Formatter.h"
31 #include "include/ceph_assert.h"
32
33 class PyFormatter : public ceph::Formatter
34 {
35 public:
36 PyFormatter (const PyFormatter&) = delete;
37 PyFormatter& operator= (const PyFormatter&) = delete;
38 PyFormatter(bool pretty = false, bool array = false)
39 {
40 // It is forbidden to instantiate me outside of the GIL,
41 // because I construct python objects right away
42
43 // Initialise cursor to an empty dict
44 if (!array) {
45 root = cursor = PyDict_New();
46 } else {
47 root = cursor = PyList_New(0);
48 }
49 }
50
51 ~PyFormatter() override
52 {
53 cursor = NULL;
54 Py_DECREF(root);
55 root = NULL;
56 }
57
58 // Obscure, don't care.
59 void open_array_section_in_ns(std::string_view name, const char *ns) override
60 {ceph_abort();}
61 void open_object_section_in_ns(std::string_view name, const char *ns) override
62 {ceph_abort();}
63
64 void reset() override
65 {
66 const bool array = PyList_Check(root);
67 Py_DECREF(root);
68 if (array) {
69 root = cursor = PyList_New(0);
70 } else {
71 root = cursor = PyDict_New();
72 }
73 }
74
75 void set_status(int status, const char* status_name) override {}
76 void output_header() override {};
77 void output_footer() override {};
78 void enable_line_break() override {};
79
80 void open_array_section(std::string_view name) override;
81 void open_object_section(std::string_view name) override;
82 void close_section() override
83 {
84 ceph_assert(cursor != root);
85 ceph_assert(!stack.empty());
86 cursor = stack.top();
87 stack.pop();
88 }
89 void dump_bool(std::string_view name, bool b) override;
90 void dump_unsigned(std::string_view name, uint64_t u) override;
91 void dump_int(std::string_view name, int64_t u) override;
92 void dump_float(std::string_view name, double d) override;
93 void dump_string(std::string_view name, std::string_view s) override;
94 std::ostream& dump_stream(std::string_view name) override;
95 void dump_format_va(std::string_view name, const char *ns, bool quoted, const char *fmt, va_list ap) override;
96
97 void flush(std::ostream& os) override
98 {
99 // This class is not a serializer: this doesn't make sense
100 ceph_abort();
101 }
102
103 int get_len() const override
104 {
105 // This class is not a serializer: this doesn't make sense
106 ceph_abort();
107 return 0;
108 }
109
110 void write_raw_data(const char *data) override
111 {
112 // This class is not a serializer: this doesn't make sense
113 ceph_abort();
114 }
115
116 PyObject *get()
117 {
118 finish_pending_streams();
119
120 Py_INCREF(root);
121 return root;
122 }
123
124 void finish_pending_streams();
125
126 private:
127 PyObject *root;
128 PyObject *cursor;
129 std::stack<PyObject *> stack;
130
131 void dump_pyobject(std::string_view name, PyObject *p);
132
133 class PendingStream {
134 public:
135 PyObject *cursor;
136 std::string name;
137 std::stringstream stream;
138 };
139
140 std::list<std::shared_ptr<PendingStream> > pending_streams;
141
142 };
143
144 #endif
145