log.cc 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. // Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #define PY_SSIZE_T_CLEAN
  15. #include <Python.h>
  16. #include <structmember.h>
  17. #include <config.h>
  18. #include <log/message_dictionary.h>
  19. using namespace isc::log;
  20. namespace {
  21. // This is for testing only. The real module will have it always set as
  22. // NULL and will use the global dictionary.
  23. MessageDictionary* testDictionary = NULL;
  24. PyObject*
  25. setTestDictionary(PyObject*, PyObject* args) {
  26. PyObject* enableO;
  27. // The API doesn't seem to provide conversion to bool,
  28. // so we do it little bit manually
  29. if (!PyArg_ParseTuple(args, "O", &enableO)) {
  30. return (NULL);
  31. }
  32. int enableI(PyObject_IsTrue(enableO));
  33. if (enableI == -1) {
  34. return (NULL);
  35. }
  36. bool enable(enableI != 0);
  37. delete testDictionary;
  38. testDictionary = NULL;
  39. try {
  40. if (enable) {
  41. testDictionary = new MessageDictionary;
  42. }
  43. }
  44. catch (const std::exception& e) {
  45. PyErr_SetString(PyExc_RuntimeError, e.what());
  46. return (NULL);
  47. }
  48. catch (...) {
  49. PyErr_SetString(PyExc_RuntimeError, "Unknown C++ exception");
  50. return (NULL);
  51. }
  52. Py_RETURN_NONE;
  53. }
  54. PyObject*
  55. createMessage(PyObject*, PyObject* args) {
  56. const char* mid;
  57. const char* text;
  58. // We parse the strings
  59. if (!PyArg_ParseTuple(args, "ss", &mid, &text)) {
  60. return (NULL);
  61. }
  62. PyObject* origMid;
  63. // And extract the original representation of the message
  64. // ID, so we can return it instead of creating another instance.
  65. // This call shouldn't fail if the previous suceeded.
  66. if (!PyArg_ParseTuple(args, "Os", &origMid, &text)) {
  67. return (NULL);
  68. }
  69. try {
  70. MessageDictionary* dict = testDictionary ? testDictionary :
  71. &MessageDictionary::globalDictionary();
  72. // We ignore the result, they will be in some kind of dupe list
  73. // if there's a problem
  74. dict->add(mid, text);
  75. }
  76. catch (const std::exception& e) {
  77. PyErr_SetString(PyExc_RuntimeError, e.what());
  78. return (NULL);
  79. }
  80. catch (...) {
  81. PyErr_SetString(PyExc_RuntimeError, "Unknown C++ exception");
  82. return (NULL);
  83. }
  84. // Return the ID
  85. Py_INCREF(origMid);
  86. return (origMid);
  87. }
  88. PyObject*
  89. getMessage(PyObject*, PyObject* args) {
  90. const char* mid;
  91. if (!PyArg_ParseTuple(args, "s", &mid)) {
  92. return (NULL);
  93. }
  94. try {
  95. MessageDictionary* dict = testDictionary ? testDictionary :
  96. &MessageDictionary::globalDictionary();
  97. const std::string& result(dict->getText(mid));
  98. if (result.empty()) {
  99. Py_RETURN_NONE;
  100. } else {
  101. return (Py_BuildValue("s", result.c_str()));
  102. }
  103. }
  104. catch (const std::exception& e) {
  105. PyErr_SetString(PyExc_RuntimeError, e.what());
  106. return (NULL);
  107. }
  108. catch (...) {
  109. PyErr_SetString(PyExc_RuntimeError, "Unknown C++ exception");
  110. return (NULL);
  111. }
  112. }
  113. PyMethodDef methods[] = {
  114. {"set_test_dictionary", &setTestDictionary, METH_VARARGS,
  115. "Set or unset testing mode for message dictionary. In testing, "
  116. "the create_message and get_message functions work on different "
  117. "than the logger-global dictionary, not polluting it."},
  118. {"create_message", &createMessage, METH_VARARGS,
  119. "Creates a new message in the dictionary. You shouldn't need to "
  120. "call this directly, it should be called by the generated message "
  121. "file. Returns the identifier to be used in logging. The text "
  122. "shouldn't be empty."},
  123. {"get_message", &getMessage, METH_VARARGS,
  124. "Get a message. This function is for testing purposes and you don't "
  125. "need to call it. It returns None if the message does not exist."},
  126. {NULL, NULL, 0, NULL}
  127. };
  128. PyModuleDef iscLog = {
  129. { PyObject_HEAD_INIT(NULL) NULL, 0, NULL},
  130. "log",
  131. "Python bindings for the classes in the isc::log namespace.\n\n"
  132. "These bindings are close match to the C++ API, but they are not complete "
  133. "(some parts are not needed) and some are done in more python-like ways.",
  134. -1,
  135. methods,
  136. NULL,
  137. NULL,
  138. NULL,
  139. NULL
  140. };
  141. }
  142. PyMODINIT_FUNC
  143. PyInit_log(void) {
  144. PyObject* mod = PyModule_Create(&iscLog);
  145. if (mod == NULL) {
  146. return (NULL);
  147. }
  148. return (mod);
  149. }