updater_inc.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. // Copyright (C) 2011,2013 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. namespace {
  15. const char* const ZoneUpdater_doc = "\
  16. The base class to make updates to a single zone.\n\
  17. \n\
  18. On construction, each derived class object will start a\n\
  19. \"transaction\" for making updates to a specific zone (this means a\n\
  20. constructor of a derived class would normally take parameters to\n\
  21. identify the zone to be updated). The underlying realization of a\n\
  22. \"transaction\" will differ for different derived classes; if it uses\n\
  23. a general purpose database as a backend, it will involve performing\n\
  24. some form of \"begin transaction\" statement for the database.\n\
  25. \n\
  26. Updates (adding or deleting RRs) are made via add_rrset() and\n\
  27. delete_rrset() methods. Until the commit() method is called the\n\
  28. changes are local to the updater object. For example, they won't be\n\
  29. visible via a ZoneFinder object, but only by the updater's own find()\n\
  30. method. The commit() completes the transaction and makes the changes\n\
  31. visible to others.\n\
  32. \n\
  33. This class does not provide an explicit \"rollback\" interface. If\n\
  34. something wrong or unexpected happens during the updates and the\n\
  35. caller wants to cancel the intermediate updates, the caller should\n\
  36. simply destroy the updater object without calling commit(). The\n\
  37. destructor is supposed to perform the \"rollback\" operation,\n\
  38. depending on the internal details of the derived class.\n\
  39. \n\
  40. This initial implementation provides a quite simple interface of\n\
  41. adding and deleting RRs (see the description of the related methods).\n\
  42. It may be revisited as we gain more experiences.\n\
  43. \n\
  44. ";
  45. const char* const ZoneUpdater_addRRset_doc = "\
  46. add_rrset(rrset) -> No return value\n\
  47. \n\
  48. Add an RRset to a zone via the updater.\n\
  49. It performs a few basic checks:\n\
  50. - Whether the RR class is identical to that for the zone to be updated\n\
  51. - Whether the RRset is not empty, i.e., it has at least one RDATA\n\
  52. - Whether the RRset is not associated with an RRSIG, i.e., whether\n\
  53. get_rrsig() on the RRset returns a NULL pointer.\n\
  54. \n\
  55. and otherwise does not check any oddity. For example, it doesn't check\n\
  56. whether the owner name of the specified RRset is a subdomain of the\n\
  57. zone's origin; it doesn't care whether or not there is already an\n\
  58. RRset of the same name and RR type in the zone, and if there is,\n\
  59. whether any of the existing RRs have duplicate RDATA with the added\n\
  60. ones. If these conditions matter the calling application must examine\n\
  61. the existing data beforehand using the ZoneFinder returned by\n\
  62. get_finder().\n\
  63. \n\
  64. The validation requirement on the associated RRSIG is temporary. If we\n\
  65. find it more reasonable and useful to allow adding a pair of RRset and\n\
  66. its RRSIG RRset as we gain experiences with the interface, we may\n\
  67. remove this restriction. Until then we explicitly check it to prevent\n\
  68. accidental misuse.\n\
  69. \n\
  70. Conceptually, on successful call to this method, the zone will have\n\
  71. the specified RRset, and if there is already an RRset of the same name\n\
  72. and RR type, these two sets will be \"merged\". \"Merged\" means that\n\
  73. a subsequent call to ZoneFinder.find() for the name and type will\n\
  74. result in success and the returned RRset will contain all previously\n\
  75. existing and newly added RDATAs with the TTL being the minimum of the\n\
  76. two RRsets. The underlying representation of the \"merged\" RRsets may\n\
  77. vary depending on the characteristic of the underlying data source.\n\
  78. For example, if it uses a general purpose database that stores each RR\n\
  79. of the same RRset separately, it may simply be a larger sets of RRs\n\
  80. based on both the existing and added RRsets; the TTLs of the RRs may\n\
  81. be different within the database, and there may even be duplicate RRs\n\
  82. in different database rows. As long as the RRset returned via\n\
  83. ZoneFinder.find() conforms to the concept of \"merge\", the actual\n\
  84. internal representation is up to the implementation.\n\
  85. \n\
  86. This method must not be called once commit() is performed. If it calls\n\
  87. after commit() the implementation must throw a isc.datasrc.Error\n\
  88. exception.\n\
  89. \n\
  90. Implementations of ZoneUpdater may not allow adding or deleting RRsets\n\
  91. after get_rrset_collection() is called. In this case, implementations\n\
  92. throw an InvalidOperation exception.\n\
  93. \n\
  94. Todo As noted above we may have to revisit the design details as we\n\
  95. gain experiences:\n\
  96. \n\
  97. - we may want to check (and maybe reject) if there is already a\n\
  98. duplicate RR (that has the same RDATA).\n\
  99. - we may want to check (and maybe reject) if there is already an RRset\n\
  100. of the same name and RR type with different TTL\n\
  101. - we may even want to check if there is already any RRset of the same\n\
  102. name and RR type.\n\
  103. - we may want to add an \"options\" parameter that can control the\n\
  104. above points\n\
  105. - we may want to have this method return a value containing the\n\
  106. information on whether there's a duplicate, etc.\n\
  107. \n\
  108. Exceptions:\n\
  109. isc.datasrc.Error Called after commit(), RRset is invalid (see above),\n\
  110. internal data source error, or wrapper error\n\
  111. \n\
  112. Parameters:\n\
  113. rrset The RRset to be added\n\
  114. \n\
  115. ";
  116. const char* const ZoneUpdater_deleteRRset_doc = "\
  117. delete_rrset(rrset) -> No return value\n\
  118. \n\
  119. Delete an RRset from a zone via the updater.\n\
  120. \n\
  121. Like add_rrset(), the detailed semantics and behavior of this method\n\
  122. may have to be revisited in a future version. The following are based\n\
  123. on the initial implementation decisions.\n\
  124. \n\
  125. - Existing RRs that don't match any of the specified RDATAs will\n\
  126. remain in the zone.\n\
  127. - Any RRs of the specified RRset that doesn't exist in the zone will\n\
  128. simply be ignored; the implementation of this method is not supposed\n\
  129. to check that condition.\n\
  130. - The TTL of the RRset is ignored; matching is only performed by the\n\
  131. owner name, RR type and RDATA\n\
  132. \n\
  133. Ignoring the TTL may not look sensible, but it's based on the\n\
  134. observation that it will result in more intuitive result, especially\n\
  135. when the underlying data source is a general purpose database. See\n\
  136. also the c++ documentation of DatabaseAccessor::DeleteRecordInZone()\n\
  137. on this point. It also matches the dynamic update protocol (RFC2136),\n\
  138. where TTLs are ignored when deleting RRs.\n\
  139. \n\
  140. This method performs a limited level of validation on the specified\n\
  141. RRset:\n\
  142. - Whether the RR class is identical to that for the zone to be updated\n\
  143. - Whether the RRset is not empty, i.e., it has at least one RDATA\n\
  144. - Whether the RRset is not associated with an RRSIG\n\
  145. \n\
  146. This method must not be called once commit() is performed. If it calls\n\
  147. after commit() the implementation must throw a isc.datasrc.Error\n\
  148. exception.\n\
  149. \n\
  150. Implementations of ZoneUpdater may not allow adding or deleting RRsets\n\
  151. after get_rrset_collection() is called. In this case, implementations\n\
  152. throw an InvalidOperation exception.\n\
  153. \n\
  154. Todo: As noted above we may have to revisit the design details as we\n\
  155. gain experiences:\n\
  156. \n\
  157. - we may want to check (and maybe reject) if some or all of the RRs\n\
  158. for the specified RRset don't exist in the zone\n\
  159. - we may want to allow an option to \"delete everything\" for\n\
  160. specified name and/or specified name + RR type.\n\
  161. - as mentioned above, we may want to include the TTL in matching the\n\
  162. deleted RRs\n\
  163. - we may want to add an \"options\" parameter that can control the\n\
  164. above points\n\
  165. - we may want to have this method return a value containing the\n\
  166. information on whether there's any RRs that are specified but don't\n\
  167. exit, the number of actually deleted RRs, etc.\n\
  168. \n\
  169. Exceptions:\n\
  170. isc.datasrc.Error Called after commit(), RRset is invalid (see above),\n\
  171. internal data source error\n\
  172. std.bad_alloc Resource allocation failure\n\
  173. \n\
  174. Parameters:\n\
  175. rrset The RRset to be deleted\n\
  176. \n\
  177. ";
  178. const char* const ZoneUpdater_commit_doc = "\
  179. commit() -> void\n\
  180. \n\
  181. Commit the updates made in the updater to the zone.\n\
  182. \n\
  183. This method completes the \"transaction\" started at the creation of\n\
  184. the updater. After successful completion of this method, the updates\n\
  185. will be visible outside the scope of the updater. The actual internal\n\
  186. behavior will defer for different derived classes. For a derived class\n\
  187. with a general purpose database as a backend, for example, this method\n\
  188. would perform a \"commit\" statement for the database.\n\
  189. \n\
  190. This operation can only be performed at most once. A duplicate call\n\
  191. must result in a isc.datasrc.Error exception.\n\
  192. \n\
  193. Exceptions:\n\
  194. isc.datasrc.Error Duplicate call of the method, internal data source\n\
  195. error, or wrapper error\n\\n\
  196. \n\
  197. ";
  198. // Modifications:
  199. // - remove reference to isc.datasrc.RRsetCollectionBase (hidden for Python
  200. // wrapper)
  201. const char* const ZoneUpdater_getRRsetCollection_doc = "\
  202. get_rrset_collection() -> isc.dns.RRsetCollectionBase \n\
  203. \n\
  204. Return an RRsetCollection for the updater.\n\
  205. \n\
  206. This method returns an RRsetCollection for the updater, implementing\n\
  207. the isc.dns.RRsetCollectionBase interface. Typically, the returned\n\
  208. RRsetCollection is a singleton for its ZoneUpdater. The returned\n\
  209. RRsetCollection object must not be used after its corresponding\n\
  210. ZoneUpdater has been destroyed. The returned RRsetCollection object\n\
  211. may be used to search RRsets from the ZoneUpdater. The actual\n\
  212. RRsetCollection returned has a behavior dependent on the ZoneUpdater\n\
  213. implementation.\n\
  214. \n\
  215. The behavior of the RRsetCollection is similar to the behavior of the\n\
  216. Zonefinder returned by get_finder(). In fact, it's redundant in a\n\
  217. sense because one can implement the dns.RRsetCollectionBase interface\n\
  218. using an updater and get_finder() interface (unless it's expected to\n\
  219. support zone iteration, and the initial implementation of the\n\
  220. RRsetCollection returned by this method doesn't support it). We\n\
  221. still provide it as an updater's method so it will be easier for an\n\
  222. updater implementation to customize the RRsetCollection\n\
  223. implementation, and also for making it easy to impose restrictions\n\
  224. described below.\n\
  225. \n\
  226. Specific data sources may have special restrictions. That's especially\n\
  227. the case for database-based data sources. Such restrictions may also\n\
  228. result in limiting the usage of the RRsetCollection as described in\n\
  229. the following paragraphs. A specific updater implementation may\n\
  230. provide more flexible behavior, but applications using this interface\n\
  231. must assume the most restricted case unless it knows it uses a\n\
  232. particular specialized updater implementation that loosens specific\n\
  233. restrictions.\n\
  234. \n\
  235. - An application must not add or delete RRsets after\n\
  236. get_rrset_collection() is called.\n\
  237. - An application must not use the returned collection from\n\
  238. get_rrset_collection() once commit() is called on the updater that\n\
  239. generates the collection.\n\
  240. \n\
  241. Implementations of ZoneUpdater may not allow adding or deleting RRsets\n\
  242. after get_rrset_collection() is called. This is because if an\n\
  243. iterator of the collection is being used at that time the modification\n\
  244. to the zone may break an internal assumption of the iterator and may\n\
  245. result in unexpected behavior. Also, the iterator may conceptually\n\
  246. hold a \"reader lock\" of the zone (in an implementation dependent\n\
  247. manner), which would prevent the addition or deletion, surprising the\n\
  248. caller (who would normally expect it to succeed).\n\
  249. \n\
  250. Implementations of ZoneUpdater may disable a previously returned\n\
  251. RRsetCollection after commit() is called. This is because the returned\n\
  252. RRsetCollection may internally rely on the conceptual transaction of\n\
  253. the updater that generates the collection (which would be literally\n\
  254. the case for database-based data sources), and once the transaction is\n\
  255. committed anything that relies on it won't be valid. If an\n\
  256. RRsetCollection is disabled, using methods such as find() and using\n\
  257. its iterator would cause an exception to be thrown.\n\
  258. \n\
  259. ";
  260. } // unnamed namespace