Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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 // 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 {};
79   void enable_line_break() override {};
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