json_feed.cc 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. // Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. #include <cc/data.h>
  7. #include <cc/json_feed.h>
  8. #include <boost/bind.hpp>
  9. #include <iostream>
  10. using namespace isc::data;
  11. using namespace isc::util;
  12. namespace isc {
  13. namespace config {
  14. const int JSONFeed::RECEIVE_START_ST;
  15. const int JSONFeed::WHITESPACE_BEFORE_JSON_ST;
  16. const int JSONFeed::JSON_START_ST;
  17. const int JSONFeed::INNER_JSON_ST;
  18. const int JSONFeed::JSON_END_ST;
  19. const int JSONFeed::FEED_OK_ST;
  20. const int JSONFeed::FEED_FAILED_ST;
  21. const int JSONFeed::DATA_READ_OK_EVT;
  22. const int JSONFeed::NEED_MORE_DATA_EVT;
  23. const int JSONFeed::MORE_DATA_PROVIDED_EVT;
  24. const int JSONFeed::FEED_OK_EVT;
  25. const int JSONFeed::FEED_FAILED_EVT;
  26. JSONFeed::JSONFeed()
  27. : StateModel(), buffer_(), error_message_(), open_scopes_(0),
  28. output_() {
  29. }
  30. void
  31. JSONFeed::initModel() {
  32. // Intialize dictionaries of events and states.
  33. initDictionaries();
  34. // Set the current state to starting state and enter the run loop.
  35. setState(RECEIVE_START_ST);
  36. // Parsing starts from here.
  37. postNextEvent(START_EVT);
  38. }
  39. void
  40. JSONFeed::poll() {
  41. try {
  42. // Process the input data until no more data is available or until
  43. // JSON feed ends with matching closing brace.
  44. do {
  45. getState(getCurrState())->run();
  46. } while (!isModelDone() && (getNextEvent() != NOP_EVT) &&
  47. (getNextEvent() != NEED_MORE_DATA_EVT));
  48. } catch (const std::exception& ex) {
  49. abortModel(ex.what());
  50. }
  51. }
  52. bool
  53. JSONFeed::needData() const {
  54. return ((getNextEvent() == NEED_MORE_DATA_EVT) ||
  55. (getNextEvent() == START_EVT));
  56. }
  57. bool
  58. JSONFeed::feedOk() const {
  59. return ((getNextEvent() == END_EVT) &&
  60. (getLastEvent() == FEED_OK_EVT));
  61. }
  62. ElementPtr
  63. JSONFeed::toElement() const {
  64. if (needData()) {
  65. isc_throw(JSONFeedError, "unable to retrieve the data form the"
  66. " JSON feed while parsing hasn't finished");
  67. }
  68. try {
  69. return (Element::fromWire(output_));
  70. } catch (const std::exception& ex) {
  71. isc_throw(JSONFeedError, ex.what());
  72. }
  73. }
  74. void
  75. JSONFeed::postBuffer(const void* buf, const size_t buf_size) {
  76. if (buf_size > 0) {
  77. // The next event is NEED_MORE_DATA_EVT when the parser wants to
  78. // signal that more data is needed. This method is called to supply
  79. // more data and thus it should change the next event to
  80. // MORE_DATA_PROVIDED_EVT.
  81. if (getNextEvent() == NEED_MORE_DATA_EVT) {
  82. transition(getCurrState(), MORE_DATA_PROVIDED_EVT);
  83. }
  84. buffer_.insert(buffer_.end(), static_cast<const char*>(buf),
  85. static_cast<const char*>(buf) + buf_size);
  86. }
  87. }
  88. void
  89. JSONFeed::defineEvents() {
  90. StateModel::defineEvents();
  91. // Define JSONFeed specific events.
  92. defineEvent(DATA_READ_OK_EVT, "DATA_READ_OK_EVT");
  93. defineEvent(NEED_MORE_DATA_EVT, "NEED_MORE_DATA_EVT");
  94. defineEvent(MORE_DATA_PROVIDED_EVT, "MORE_DATA_PROVIDED_EVT");
  95. defineEvent(FEED_OK_EVT, "FEED_OK_EVT");
  96. defineEvent(FEED_FAILED_EVT, "FEED_FAILED_EVT");
  97. }
  98. void
  99. JSONFeed::verifyEvents() {
  100. StateModel::verifyEvents();
  101. getEvent(DATA_READ_OK_EVT);
  102. getEvent(NEED_MORE_DATA_EVT);
  103. getEvent(MORE_DATA_PROVIDED_EVT);
  104. getEvent(FEED_OK_EVT);
  105. getEvent(FEED_FAILED_EVT);
  106. }
  107. void
  108. JSONFeed::defineStates() {
  109. // Call parent class implementation first.
  110. StateModel::defineStates();
  111. defineState(RECEIVE_START_ST, "RECEIVE_START_ST",
  112. boost::bind(&JSONFeed::receiveStartHandler, this));
  113. defineState(WHITESPACE_BEFORE_JSON_ST, "WHITESPACE_BEFORE_JSON_ST",
  114. boost::bind(&JSONFeed::whiteSpaceBeforeJSONHandler, this));
  115. defineState(INNER_JSON_ST, "INNER_JSON_ST",
  116. boost::bind(&JSONFeed::innerJSONHandler, this));
  117. defineState(JSON_END_ST, "JSON_END_ST",
  118. boost::bind(&JSONFeed::endJSONHandler, this));
  119. }
  120. void
  121. JSONFeed::feedFailure(const std::string& error_msg) {
  122. error_message_ = error_msg + " : " + getContextStr();
  123. transition(FEED_FAILED_ST, FEED_FAILED_EVT);
  124. }
  125. void
  126. JSONFeed::onModelFailure(const std::string& explanation) {
  127. if (error_message_.empty()) {
  128. error_message_ = explanation;
  129. }
  130. }
  131. bool
  132. JSONFeed::popNextFromBuffer(char& next) {
  133. // If there are any characters in the buffer, pop next.
  134. if (!buffer_.empty()) {
  135. next = buffer_.front();
  136. buffer_.pop_front();
  137. return (true);
  138. }
  139. return (false);
  140. }
  141. char
  142. JSONFeed::getNextFromBuffer() {
  143. unsigned int ev = getNextEvent();
  144. char c = '\0';
  145. // The caller should always provide additional data when the
  146. // NEED_MORE_DATA_EVT occurrs. If the next event is still
  147. // NEED_MORE_DATA_EVT it indicates that the caller hasn't provided
  148. // the data.
  149. if (ev == NEED_MORE_DATA_EVT) {
  150. isc_throw(JSONFeedError,
  151. "JSONFeed requires new data to progress, but no data"
  152. " have been provided. The transaction is aborted to avoid"
  153. " a deadlock.");
  154. } else {
  155. // Try to pop next character from the buffer.
  156. const bool data_exist = popNextFromBuffer(c);
  157. if (!data_exist) {
  158. // There is no more data so it is really not possible that we're
  159. // at MORE_DATA_PROVIDED_EVT.
  160. if (ev == MORE_DATA_PROVIDED_EVT) {
  161. isc_throw(JSONFeedError,
  162. "JSONFeed state indicates that new data have been"
  163. " provided to be parsed, but the transaction buffer"
  164. " contains no new data.");
  165. } else {
  166. // If there is no more data we should set NEED_MORE_DATA_EVT
  167. // event to indicate that new data should be provided.
  168. transition(getCurrState(), NEED_MORE_DATA_EVT);
  169. }
  170. }
  171. }
  172. return (c);
  173. }
  174. void
  175. JSONFeed::invalidEventError(const std::string& handler_name,
  176. const unsigned int event) {
  177. isc_throw(JSONFeedError, handler_name << ": "
  178. << " invalid event " << getEventLabel(static_cast<int>(event)));
  179. }
  180. void
  181. JSONFeed::receiveStartHandler() {
  182. char c = getNextFromBuffer();
  183. if (getNextEvent() != NEED_MORE_DATA_EVT) {
  184. switch(getNextEvent()) {
  185. case START_EVT:
  186. switch (c) {
  187. case '\t':
  188. case '\n':
  189. case '\r':
  190. case ' ':
  191. transition(WHITESPACE_BEFORE_JSON_ST, DATA_READ_OK_EVT);
  192. return;
  193. case '{':
  194. case '[':
  195. output_.push_back(c);
  196. ++open_scopes_;
  197. transition(INNER_JSON_ST, DATA_READ_OK_EVT);
  198. return;
  199. default:
  200. feedFailure("invalid first character " + std::string(1, c));
  201. }
  202. default:
  203. invalidEventError("receiveStartHandler", getNextEvent());
  204. }
  205. }
  206. }
  207. void
  208. JSONFeed::whiteSpaceBeforeJSONHandler() {
  209. char c = getNextFromBuffer();
  210. if (getNextEvent() != NEED_MORE_DATA_EVT) {
  211. switch (c) {
  212. case '\t':
  213. case '\n':
  214. case '\r':
  215. case ' ':
  216. transition(getCurrState(), DATA_READ_OK_EVT);
  217. break;
  218. case '{':
  219. case '[':
  220. output_.push_back(c);
  221. ++open_scopes_;
  222. transition(INNER_JSON_ST, DATA_READ_OK_EVT);
  223. break;
  224. default:
  225. feedFailure("invalid character " + std::string(1, c));
  226. }
  227. }
  228. }
  229. void
  230. JSONFeed::innerJSONHandler() {
  231. char c = getNextFromBuffer();
  232. if (getNextEvent() != NEED_MORE_DATA_EVT) {
  233. output_.push_back(c);
  234. switch(c) {
  235. case '{':
  236. case '[':
  237. transition(getCurrState(), DATA_READ_OK_EVT);
  238. ++open_scopes_;
  239. break;
  240. case '}':
  241. case ']':
  242. if (--open_scopes_ == 0) {
  243. transition(JSON_END_ST, FEED_OK_EVT);
  244. } else {
  245. transition(getCurrState(), DATA_READ_OK_EVT);
  246. }
  247. break;
  248. default:
  249. transition(getCurrState(), DATA_READ_OK_EVT);
  250. }
  251. }
  252. }
  253. void
  254. JSONFeed::endJSONHandler() {
  255. switch (getNextEvent()) {
  256. case FEED_OK_EVT:
  257. transition(END_ST, END_EVT);
  258. break;
  259. case FEED_FAILED_EVT:
  260. abortModel("reading into JSON feed failed");
  261. break;
  262. default:
  263. invalidEventError("endJSONHandler", getNextEvent());
  264. }
  265. }
  266. } // end of namespace config
  267. } // end of namespace isc