Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / mgr / PyFormatter.cc
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
18 #include "PyFormatter.h"
19
20 #define LARGE_SIZE 1024
21
22
23 void PyFormatter::open_array_section(const char *name)
24 {
25   PyObject *list = PyList_New(0);
26   dump_pyobject(name, list);
27   stack.push(cursor);
28   cursor = list;
29 }
30
31 void PyFormatter::open_object_section(const char *name)
32 {
33   PyObject *dict = PyDict_New();
34   dump_pyobject(name, dict);
35   stack.push(cursor);
36   cursor = dict;
37 }
38
39 void PyFormatter::dump_unsigned(const char *name, uint64_t u)
40 {
41   PyObject *p = PyLong_FromLongLong(u);
42   assert(p);
43   dump_pyobject(name, p);
44 }
45
46 void PyFormatter::dump_int(const char *name, int64_t u)
47 {
48   PyObject *p = PyLong_FromLongLong(u);
49   assert(p);
50   dump_pyobject(name, p);
51 }
52
53 void PyFormatter::dump_float(const char *name, double d)
54 {
55   dump_pyobject(name, PyFloat_FromDouble(d));
56 }
57
58 void PyFormatter::dump_string(const char *name, const std::string& s)
59 {
60   dump_pyobject(name, PyString_FromString(s.c_str()));
61 }
62
63 void PyFormatter::dump_bool(const char *name, bool b)
64 {
65   if (b) {
66     Py_INCREF(Py_True);
67     dump_pyobject(name, Py_True);
68   } else {
69     Py_INCREF(Py_False);
70     dump_pyobject(name, Py_False);
71   }
72 }
73
74 std::ostream& PyFormatter::dump_stream(const char *name)
75 {
76   // Give the caller an ostream, construct a PyString,
77   // and remember the association between the two.  On flush,
78   // we'll read from the ostream into the PyString
79   auto ps = std::make_shared<PendingStream>();
80   ps->cursor = cursor;
81   ps->name = name;
82
83   pending_streams.push_back(ps);
84
85   return ps->stream;
86 }
87
88 void PyFormatter::dump_format_va(const char *name, const char *ns, bool quoted, const char *fmt, va_list ap)
89 {
90   char buf[LARGE_SIZE];
91   vsnprintf(buf, LARGE_SIZE, fmt, ap);
92
93   dump_pyobject(name, PyString_FromString(buf));
94 }
95
96 /**
97  * Steals reference to `p`
98  */
99 void PyFormatter::dump_pyobject(const char *name, PyObject *p)
100 {
101   if (PyList_Check(cursor)) {
102     PyList_Append(cursor, p);
103     Py_DECREF(p);
104   } else if (PyDict_Check(cursor)) {
105     PyObject *key = PyString_FromString(name);
106     PyDict_SetItem(cursor, key, p);
107     Py_DECREF(key);
108     Py_DECREF(p);
109   } else {
110     ceph_abort();
111   }
112 }
113
114 void PyFormatter::finish_pending_streams()
115 {
116   for (const auto &i : pending_streams) {
117     PyObject *tmp_cur = cursor;
118     cursor = i->cursor;
119     dump_pyobject(
120         i->name.c_str(),
121         PyString_FromString(i->stream.str().c_str()));
122     cursor = tmp_cur;
123   }
124
125   pending_streams.clear();
126 }
127