]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | // Python's pyconfig-64.h conflicts with ceph's acconfig.h | |
23 | #undef HAVE_SYS_WAIT_H | |
24 | #undef HAVE_UNISTD_H | |
25 | #undef HAVE_UTIME_H | |
26 | #undef _POSIX_C_SOURCE | |
27 | #undef _XOPEN_SOURCE | |
28 | ||
29 | #include <stack> | |
30 | #include <memory> | |
31 | #include <list> | |
32 | ||
33 | #include "common/Formatter.h" | |
34 | #include "include/assert.h" | |
35 | ||
36 | class PyFormatter : public ceph::Formatter | |
37 | { | |
38 | public: | |
39 | PyFormatter(bool pretty = false, bool array = false) | |
40 | { | |
41 | // It is forbidden to instantiate me outside of the GIL, | |
42 | // because I construct python objects right away | |
43 | ||
44 | // Initialise cursor to an empty dict | |
45 | if (!array) { | |
46 | root = cursor = PyDict_New(); | |
47 | } else { | |
48 | root = cursor = PyList_New(0); | |
49 | } | |
50 | } | |
51 | ||
52 | ~PyFormatter() override | |
53 | { | |
54 | cursor = NULL; | |
55 | Py_DECREF(root); | |
56 | root = NULL; | |
57 | } | |
58 | ||
59 | // Obscure, don't care. | |
60 | void open_array_section_in_ns(const char *name, const char *ns) override | |
61 | {ceph_abort();} | |
62 | void open_object_section_in_ns(const char *name, const char *ns) override | |
63 | {ceph_abort();} | |
64 | ||
65 | void reset() override | |
66 | { | |
67 | const bool array = PyList_Check(root); | |
68 | Py_DECREF(root); | |
69 | if (array) { | |
70 | root = cursor = PyList_New(0); | |
71 | } else { | |
72 | root = cursor = PyDict_New(); | |
73 | } | |
74 | } | |
75 | ||
76 | void set_status(int status, const char* status_name) override {} | |
77 | void output_header() override {}; | |
78 | void output_footer() override {}; | |
181888fb | 79 | void enable_line_break() override {}; |
7c673cae FG |
80 | |
81 | void open_array_section(const char *name) override; | |
82 | void open_object_section(const char *name) override; | |
83 | void close_section() override | |
84 | { | |
85 | assert(cursor != root); | |
86 | assert(!stack.empty()); | |
87 | cursor = stack.top(); | |
88 | stack.pop(); | |
89 | } | |
90 | void dump_bool(const char *name, bool b) override; | |
91 | void dump_unsigned(const char *name, uint64_t u) override; | |
92 | void dump_int(const char *name, int64_t u) override; | |
93 | void dump_float(const char *name, double d) override; | |
94 | void dump_string(const char *name, const std::string& s) override; | |
95 | std::ostream& dump_stream(const char *name) override; | |
96 | void dump_format_va(const char *name, const char *ns, bool quoted, const char *fmt, va_list ap) override; | |
97 | ||
98 | void flush(std::ostream& os) override | |
99 | { | |
100 | // This class is not a serializer: this doens't make sense | |
101 | ceph_abort(); | |
102 | } | |
103 | ||
104 | int get_len() const override | |
105 | { | |
106 | // This class is not a serializer: this doens't make sense | |
107 | ceph_abort(); | |
108 | return 0; | |
109 | } | |
110 | ||
111 | void write_raw_data(const char *data) override | |
112 | { | |
113 | // This class is not a serializer: this doens't make sense | |
114 | ceph_abort(); | |
115 | } | |
116 | ||
117 | PyObject *get() | |
118 | { | |
119 | finish_pending_streams(); | |
120 | ||
121 | Py_INCREF(root); | |
122 | return root; | |
123 | } | |
124 | ||
125 | void finish_pending_streams(); | |
126 | ||
127 | private: | |
128 | PyObject *root; | |
129 | PyObject *cursor; | |
130 | std::stack<PyObject *> stack; | |
131 | ||
132 | void dump_pyobject(const char *name, PyObject *p); | |
133 | ||
134 | class PendingStream { | |
135 | public: | |
136 | PyObject *cursor; | |
137 | std::string name; | |
138 | std::stringstream stream; | |
139 | }; | |
140 | ||
141 | std::list<std::shared_ptr<PendingStream> > pending_streams; | |
142 | ||
143 | }; | |
144 | ||
145 | #endif | |
146 |