fake_resolution.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // Copyright (C) 2009 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. #ifndef FAKE_RESOLUTION_H
  15. #define FAKE_RESOLUTION_H
  16. #include <boost/function.hpp>
  17. #include <boost/shared_ptr.hpp>
  18. namespace isc {
  19. namespace resolver {
  20. namespace bench {
  21. /// \brief The kind of task a FakeQuery might want to perform.
  22. ///
  23. /// The benchmark should examine which kind of task the query needs to perform
  24. /// to progress forward. According to the task, some resources might need to be
  25. /// locked, something re-scheduled, or such.
  26. enum Task {
  27. /// \brief Some CPU-bound computation.
  28. ///
  29. /// The query needs to do some computation without any shared resources.
  30. /// This might be parsing or rendering of the query, verification of
  31. /// signatures, etc.
  32. Compute,
  33. /// \brief The query needs to read data from cache.
  34. CacheRead,
  35. /// \brief The query needs to modify the cache.
  36. CacheWrite,
  37. /// \brief A response is to be sent.
  38. ///
  39. /// This needs to access the interface/socket. If the socket is shared
  40. /// between threads, it might need to lock it.
  41. Send,
  42. /// \brief An answer from upstream server is needed.
  43. ///
  44. /// The query needs to send a query to some authoritative server and wait
  45. /// for the answer. Something might need to be locked (or not, depending
  46. /// on the architecture of the thing that sends and receives). Also, the
  47. /// task will not complete immediately, the callback of performTask
  48. /// will be called at later time.
  49. Upstream
  50. };
  51. class FakeInterface;
  52. /// \brief Imitation of the work done to resolve a query.
  53. ///
  54. /// An object of this class represents some fake work that should look like
  55. /// the work needed to perform resolution of one query. No real work is done,
  56. /// but several steps are scheduled, with characteristics hopefully
  57. /// corresponding to steps of the real query.
  58. ///
  59. /// The idea is that benchmark will repeatedly check if the query is done.
  60. /// If not, it examines the next task by calling nextTask(). Depending on
  61. /// the result, it'd lock or prepare any shared resources. After that, it'd
  62. /// call performTask() to do the task. Once the query calls the callback
  63. /// passed, it can proceed to the next step.
  64. ///
  65. /// See naive_resolver.cc for example code how this could be done.
  66. class FakeQuery {
  67. public:
  68. /// \brief Callback to signify a task has been performed.
  69. typedef boost::function<void()> StepCallback;
  70. /// \brief Is work on the query completely done?
  71. ///
  72. /// If this returns true, do not call performTask or nextTask any more.
  73. /// The resolution is done.
  74. ///
  75. /// \throw isc::InvalidOperation if upstream query is still in progress.
  76. bool done() const;
  77. /// \brief Perform next step in the resolution.
  78. ///
  79. /// Do whatever is needed to be done for the next step of resolution.
  80. /// Once the step is done, the callback is called.
  81. ///
  82. /// The callback is usually called from within this call. However, in
  83. /// the case when the nextTask() returned `Upstream`, the call to the
  84. /// callback is delayed for some period of time after the method
  85. /// returns.
  86. ///
  87. /// \throw isc::InvalidOperation if it is called when done() is true, or
  88. /// if an upstream query is still in progress (performTask was called
  89. /// before and the callback was not called by the query yet).
  90. void performTask(const StepCallback& callback);
  91. /// \brief Examine the kind of the next resolution process.
  92. ///
  93. /// Call this to know what kind of task will performTask do next.
  94. ///
  95. /// \throw isc::InvalidOperation if it is called when done() is true, or
  96. /// if an upstream query is still in progress (performTask was called
  97. /// before and the callback was not called by the query yet).
  98. Task nextTask() const;
  99. /// \brief Move network communication to different interface.
  100. ///
  101. /// By default, a query does all the "communication" on the interface
  102. /// it was born on. This may be used to move a query from one interface
  103. /// to another.
  104. ///
  105. /// You don't have to lock either of the interfaces to do so, this
  106. /// only switches the data in the query.
  107. ///
  108. /// \throw isc::InvalidOperation if it is called while an upstream query
  109. /// is in progress.
  110. void migrateTo(FakeInterface& dst_interface);
  111. };
  112. typedef boost::shared_ptr<FakeQuery> FakeQueryPtr;
  113. /// \brief An imitation of interface for receiving queries.
  114. ///
  115. /// This is effectively a little bit smarter factory for queries. You can
  116. /// request a new query from it, or let process events (incoming answers).
  117. ///
  118. /// It contains its own event loop. If the benchmark has more threads, have
  119. /// one in each of the threads (if the threads ever handles network
  120. /// communication -- if it accepts queries, sends answers or does upstream
  121. /// queries).
  122. ///
  123. /// If the model simulated would share the same interface between multiple
  124. /// threads, it is better to have one in each thread as well, but lock
  125. /// access so only one is used at once (no idea what happens if ASIO loop is
  126. /// accessed from multiple threads).
  127. class FakeInterface {
  128. public:
  129. /// \brief Wait for answers from upstream servers.
  130. ///
  131. /// Wait until at least one "answer" comes from the remote server. This
  132. /// will effectively block the calling thread until it is time to call
  133. /// a callback of performTask.
  134. ///
  135. /// It is not legal to call it without any outstanding upstream queries
  136. /// on this interface. However, the situation is not explicitly checked.
  137. ///
  138. /// \note Due to internal implementation, it is not impossible no or more
  139. /// than one callbacks to be called from within this method.
  140. void processEvents();
  141. /// \brief Accept another query.
  142. ///
  143. /// Generate a new fake query to resolve.
  144. ///
  145. /// This method might call callbacks of other queries waiting for upstream
  146. /// answer.
  147. ///
  148. /// This returns a NULL pointer when there are no more queries to answer
  149. /// (the number designated for the benchmark was reached).
  150. FakeQueryPtr receiveQuery();
  151. };
  152. }
  153. }
  154. }
  155. #endif