amps-python-client 5.3.4.1__zip

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (550) hide show
  1. amps-python-client-5.3.4.1/HISTORY +7 -0
  2. amps-python-client-5.3.4.1/LICENSE +157 -0
  3. amps-python-client-5.3.4.1/PKG-INFO +112 -0
  4. amps-python-client-5.3.4.1/README.md +96 -0
  5. amps-python-client-5.3.4.1/docs/command-reference/doctrees/chapters/ack-messages.doctree +0 -0
  6. amps-python-client-5.3.4.1/docs/command-reference/doctrees/chapters/content-messages.doctree +0 -0
  7. amps-python-client-5.3.4.1/docs/command-reference/doctrees/chapters/intro.doctree +0 -0
  8. amps-python-client-5.3.4.1/docs/command-reference/doctrees/chapters/logon.doctree +0 -0
  9. amps-python-client-5.3.4.1/docs/command-reference/doctrees/chapters/protocol-reference.doctree +0 -0
  10. amps-python-client-5.3.4.1/docs/command-reference/doctrees/chapters/publishing.doctree +0 -0
  11. amps-python-client-5.3.4.1/docs/command-reference/doctrees/chapters/query-delimiters.doctree +0 -0
  12. amps-python-client-5.3.4.1/docs/command-reference/doctrees/chapters/query-subscribe.doctree +0 -0
  13. amps-python-client-5.3.4.1/docs/command-reference/doctrees/chapters/removing.doctree +0 -0
  14. amps-python-client-5.3.4.1/docs/command-reference/doctrees/chapters/utilities.doctree +0 -0
  15. amps-python-client-5.3.4.1/docs/command-reference/doctrees/environment.pickle +0 -0
  16. amps-python-client-5.3.4.1/docs/command-reference/doctrees/index.doctree +0 -0
  17. amps-python-client-5.3.4.1/docs/command-reference/html/.buildinfo +4 -0
  18. amps-python-client-5.3.4.1/docs/command-reference/html/_images/caution.svg +25 -0
  19. amps-python-client-5.3.4.1/docs/command-reference/html/_sources/chapters/ack-messages.rst.txt +32 -0
  20. amps-python-client-5.3.4.1/docs/command-reference/html/_sources/chapters/content-messages.rst.txt +27 -0
  21. amps-python-client-5.3.4.1/docs/command-reference/html/_sources/chapters/intro.rst.txt +43 -0
  22. amps-python-client-5.3.4.1/docs/command-reference/html/_sources/chapters/logon.rst.txt +231 -0
  23. amps-python-client-5.3.4.1/docs/command-reference/html/_sources/chapters/protocol-reference.rst.txt +1474 -0
  24. amps-python-client-5.3.4.1/docs/command-reference/html/_sources/chapters/publishing.rst.txt +25 -0
  25. amps-python-client-5.3.4.1/docs/command-reference/html/_sources/chapters/query-delimiters.rst.txt +12 -0
  26. amps-python-client-5.3.4.1/docs/command-reference/html/_sources/chapters/query-subscribe.rst.txt +23 -0
  27. amps-python-client-5.3.4.1/docs/command-reference/html/_sources/chapters/removing.rst.txt +6 -0
  28. amps-python-client-5.3.4.1/docs/command-reference/html/_sources/chapters/utilities.rst.txt +13 -0
  29. amps-python-client-5.3.4.1/docs/command-reference/html/_sources/index.rst.txt +56 -0
  30. amps-python-client-5.3.4.1/docs/command-reference/html/_static/ajax-loader.gif +0 -0
  31. amps-python-client-5.3.4.1/docs/command-reference/html/_static/alabaster.css +699 -0
  32. amps-python-client-5.3.4.1/docs/command-reference/html/_static/basic.css +632 -0
  33. amps-python-client-5.3.4.1/docs/command-reference/html/_static/comment-bright.png +0 -0
  34. amps-python-client-5.3.4.1/docs/command-reference/html/_static/comment-close.png +0 -0
  35. amps-python-client-5.3.4.1/docs/command-reference/html/_static/comment.png +0 -0
  36. amps-python-client-5.3.4.1/docs/command-reference/html/_static/custom.css +192 -0
  37. amps-python-client-5.3.4.1/docs/command-reference/html/_static/custom.css.backup +161 -0
  38. amps-python-client-5.3.4.1/docs/command-reference/html/_static/doctools.js +287 -0
  39. amps-python-client-5.3.4.1/docs/command-reference/html/_static/down-pressed.png +0 -0
  40. amps-python-client-5.3.4.1/docs/command-reference/html/_static/down.png +0 -0
  41. amps-python-client-5.3.4.1/docs/command-reference/html/_static/file.png +0 -0
  42. amps-python-client-5.3.4.1/docs/command-reference/html/_static/flag_logo.png +0 -0
  43. amps-python-client-5.3.4.1/docs/command-reference/html/_static/flag_logo.svg +153 -0
  44. amps-python-client-5.3.4.1/docs/command-reference/html/_static/jquery-3.1.0.js +10074 -0
  45. amps-python-client-5.3.4.1/docs/command-reference/html/_static/jquery.js +4 -0
  46. amps-python-client-5.3.4.1/docs/command-reference/html/_static/minus.png +0 -0
  47. amps-python-client-5.3.4.1/docs/command-reference/html/_static/plus.png +0 -0
  48. amps-python-client-5.3.4.1/docs/command-reference/html/_static/pygments.css +74 -0
  49. amps-python-client-5.3.4.1/docs/command-reference/html/_static/searchtools.js +758 -0
  50. amps-python-client-5.3.4.1/docs/command-reference/html/_static/underscore-1.3.1.js +999 -0
  51. amps-python-client-5.3.4.1/docs/command-reference/html/_static/underscore.js +31 -0
  52. amps-python-client-5.3.4.1/docs/command-reference/html/_static/up-pressed.png +0 -0
  53. amps-python-client-5.3.4.1/docs/command-reference/html/_static/up.png +0 -0
  54. amps-python-client-5.3.4.1/docs/command-reference/html/_static/websupport.js +808 -0
  55. amps-python-client-5.3.4.1/docs/command-reference/html/chapters/ack-messages.html +417 -0
  56. amps-python-client-5.3.4.1/docs/command-reference/html/chapters/content-messages.html +417 -0
  57. amps-python-client-5.3.4.1/docs/command-reference/html/chapters/intro.html +126 -0
  58. amps-python-client-5.3.4.1/docs/command-reference/html/chapters/logon.html +295 -0
  59. amps-python-client-5.3.4.1/docs/command-reference/html/chapters/protocol-reference.html +1190 -0
  60. amps-python-client-5.3.4.1/docs/command-reference/html/chapters/publishing.html +436 -0
  61. amps-python-client-5.3.4.1/docs/command-reference/html/chapters/query-delimiters.html +173 -0
  62. amps-python-client-5.3.4.1/docs/command-reference/html/chapters/query-subscribe.html +2123 -0
  63. amps-python-client-5.3.4.1/docs/command-reference/html/chapters/removing.html +299 -0
  64. amps-python-client-5.3.4.1/docs/command-reference/html/chapters/utilities.html +287 -0
  65. amps-python-client-5.3.4.1/docs/command-reference/html/genindex.html +97 -0
  66. amps-python-client-5.3.4.1/docs/command-reference/html/index.html +138 -0
  67. amps-python-client-5.3.4.1/docs/command-reference/html/objects.inv +0 -0
  68. amps-python-client-5.3.4.1/docs/command-reference/html/search.html +107 -0
  69. amps-python-client-5.3.4.1/docs/command-reference/html/searchindex.js +1 -0
  70. amps-python-client-5.3.4.1/docs/html/.buildinfo +4 -0
  71. amps-python-client-5.3.4.1/docs/html/_sources/code.rst.txt +6 -0
  72. amps-python-client-5.3.4.1/docs/html/_sources/index.rst.txt +29 -0
  73. amps-python-client-5.3.4.1/docs/html/_static/ajax-loader.gif +0 -0
  74. amps-python-client-5.3.4.1/docs/html/_static/basic.css +632 -0
  75. amps-python-client-5.3.4.1/docs/html/_static/classic.css +261 -0
  76. amps-python-client-5.3.4.1/docs/html/_static/comment-bright.png +0 -0
  77. amps-python-client-5.3.4.1/docs/html/_static/comment-close.png +0 -0
  78. amps-python-client-5.3.4.1/docs/html/_static/comment.png +0 -0
  79. amps-python-client-5.3.4.1/docs/html/_static/default.css +1 -0
  80. amps-python-client-5.3.4.1/docs/html/_static/doctools.js +287 -0
  81. amps-python-client-5.3.4.1/docs/html/_static/down-pressed.png +0 -0
  82. amps-python-client-5.3.4.1/docs/html/_static/down.png +0 -0
  83. amps-python-client-5.3.4.1/docs/html/_static/file.png +0 -0
  84. amps-python-client-5.3.4.1/docs/html/_static/jquery-3.1.0.js +10074 -0
  85. amps-python-client-5.3.4.1/docs/html/_static/jquery.js +4 -0
  86. amps-python-client-5.3.4.1/docs/html/_static/minus.png +0 -0
  87. amps-python-client-5.3.4.1/docs/html/_static/plus.png +0 -0
  88. amps-python-client-5.3.4.1/docs/html/_static/pygments.css +74 -0
  89. amps-python-client-5.3.4.1/docs/html/_static/searchtools.js +758 -0
  90. amps-python-client-5.3.4.1/docs/html/_static/sidebar.js +159 -0
  91. amps-python-client-5.3.4.1/docs/html/_static/underscore-1.3.1.js +999 -0
  92. amps-python-client-5.3.4.1/docs/html/_static/underscore.js +31 -0
  93. amps-python-client-5.3.4.1/docs/html/_static/up-pressed.png +0 -0
  94. amps-python-client-5.3.4.1/docs/html/_static/up.png +0 -0
  95. amps-python-client-5.3.4.1/docs/html/_static/websupport.js +808 -0
  96. amps-python-client-5.3.4.1/docs/html/code.html +6503 -0
  97. amps-python-client-5.3.4.1/docs/html/genindex.html +1361 -0
  98. amps-python-client-5.3.4.1/docs/html/index.html +131 -0
  99. amps-python-client-5.3.4.1/docs/html/objects.inv +0 -0
  100. amps-python-client-5.3.4.1/docs/html/py-modindex.html +111 -0
  101. amps-python-client-5.3.4.1/docs/html/search.html +107 -0
  102. amps-python-client-5.3.4.1/docs/html/searchindex.js +1 -0
  103. amps-python-client-5.3.4.1/docs/python/doctrees/chapters/advanced-topics.doctree +0 -0
  104. amps-python-client-5.3.4.1/docs/python/doctrees/chapters/cpp-compiler-list.doctree +0 -0
  105. amps-python-client-5.3.4.1/docs/python/doctrees/chapters/cpp-feature-table.doctree +0 -0
  106. amps-python-client-5.3.4.1/docs/python/doctrees/chapters/creating-commands.doctree +0 -0
  107. amps-python-client-5.3.4.1/docs/python/doctrees/chapters/deltas.doctree +0 -0
  108. amps-python-client-5.3.4.1/docs/python/doctrees/chapters/error-handling.doctree +0 -0
  109. amps-python-client-5.3.4.1/docs/python/doctrees/chapters/exceptions.doctree +0 -0
  110. amps-python-client-5.3.4.1/docs/python/doctrees/chapters/first-program.doctree +0 -0
  111. amps-python-client-5.3.4.1/docs/python/doctrees/chapters/high-availability.doctree +0 -0
  112. amps-python-client-5.3.4.1/docs/python/doctrees/chapters/installing.doctree +0 -0
  113. amps-python-client-5.3.4.1/docs/python/doctrees/chapters/introduction.doctree +0 -0
  114. amps-python-client-5.3.4.1/docs/python/doctrees/chapters/moving-from-python-lite.doctree +0 -0
  115. amps-python-client-5.3.4.1/docs/python/doctrees/chapters/performance-tips.doctree +0 -0
  116. amps-python-client-5.3.4.1/docs/python/doctrees/chapters/queues.doctree +0 -0
  117. amps-python-client-5.3.4.1/docs/python/doctrees/chapters/sow.doctree +0 -0
  118. amps-python-client-5.3.4.1/docs/python/doctrees/chapters/subscriptions.doctree +0 -0
  119. amps-python-client-5.3.4.1/docs/python/doctrees/chapters/utilities.doctree +0 -0
  120. amps-python-client-5.3.4.1/docs/python/doctrees/environment.pickle +0 -0
  121. amps-python-client-5.3.4.1/docs/python/doctrees/index.doctree +0 -0
  122. amps-python-client-5.3.4.1/docs/python/html/.buildinfo +4 -0
  123. amps-python-client-5.3.4.1/docs/python/html/_images/caution.png +0 -0
  124. amps-python-client-5.3.4.1/docs/python/html/_images/caution.svg +25 -0
  125. amps-python-client-5.3.4.1/docs/python/html/_images/connection_string.svg +461 -0
  126. amps-python-client-5.3.4.1/docs/python/html/_images/important.png +0 -0
  127. amps-python-client-5.3.4.1/docs/python/html/_images/important.svg +25 -0
  128. amps-python-client-5.3.4.1/docs/python/html/_images/tip.png +0 -0
  129. amps-python-client-5.3.4.1/docs/python/html/_images/tip.svg +31 -0
  130. amps-python-client-5.3.4.1/docs/python/html/_images/warning.png +0 -0
  131. amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/advanced-topics.rst.txt +398 -0
  132. amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/cpp-compiler-list.rst.txt +6 -0
  133. amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/cpp-feature-table.rst.txt +26 -0
  134. amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/creating-commands.rst.txt +159 -0
  135. amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/deltas.rst.txt +79 -0
  136. amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/error-handling.rst.txt +482 -0
  137. amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/exceptions.rst.txt +128 -0
  138. amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/first-program.rst.txt +142 -0
  139. amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/high-availability.rst.txt +876 -0
  140. amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/installing.rst.txt +184 -0
  141. amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/introduction.rst.txt +50 -0
  142. amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/moving-from-python-lite.rst.txt +32 -0
  143. amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/performance-tips.rst.txt +434 -0
  144. amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/queues.rst.txt +282 -0
  145. amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/sow.rst.txt +292 -0
  146. amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/subscriptions.rst.txt +374 -0
  147. amps-python-client-5.3.4.1/docs/python/html/_sources/chapters/utilities.rst.txt +214 -0
  148. amps-python-client-5.3.4.1/docs/python/html/_sources/index.rst.txt +44 -0
  149. amps-python-client-5.3.4.1/docs/python/html/_static/ajax-loader.gif +0 -0
  150. amps-python-client-5.3.4.1/docs/python/html/_static/alabaster.css +699 -0
  151. amps-python-client-5.3.4.1/docs/python/html/_static/basic.css +632 -0
  152. amps-python-client-5.3.4.1/docs/python/html/_static/comment-bright.png +0 -0
  153. amps-python-client-5.3.4.1/docs/python/html/_static/comment-close.png +0 -0
  154. amps-python-client-5.3.4.1/docs/python/html/_static/comment.png +0 -0
  155. amps-python-client-5.3.4.1/docs/python/html/_static/custom.css +192 -0
  156. amps-python-client-5.3.4.1/docs/python/html/_static/custom.css.backup +161 -0
  157. amps-python-client-5.3.4.1/docs/python/html/_static/doctools.js +287 -0
  158. amps-python-client-5.3.4.1/docs/python/html/_static/down-pressed.png +0 -0
  159. amps-python-client-5.3.4.1/docs/python/html/_static/down.png +0 -0
  160. amps-python-client-5.3.4.1/docs/python/html/_static/file.png +0 -0
  161. amps-python-client-5.3.4.1/docs/python/html/_static/flag_logo.png +0 -0
  162. amps-python-client-5.3.4.1/docs/python/html/_static/flag_logo.svg +153 -0
  163. amps-python-client-5.3.4.1/docs/python/html/_static/jquery-3.1.0.js +10074 -0
  164. amps-python-client-5.3.4.1/docs/python/html/_static/jquery.js +4 -0
  165. amps-python-client-5.3.4.1/docs/python/html/_static/minus.png +0 -0
  166. amps-python-client-5.3.4.1/docs/python/html/_static/plus.png +0 -0
  167. amps-python-client-5.3.4.1/docs/python/html/_static/pygments.css +74 -0
  168. amps-python-client-5.3.4.1/docs/python/html/_static/searchtools.js +758 -0
  169. amps-python-client-5.3.4.1/docs/python/html/_static/underscore-1.3.1.js +999 -0
  170. amps-python-client-5.3.4.1/docs/python/html/_static/underscore.js +31 -0
  171. amps-python-client-5.3.4.1/docs/python/html/_static/up-pressed.png +0 -0
  172. amps-python-client-5.3.4.1/docs/python/html/_static/up.png +0 -0
  173. amps-python-client-5.3.4.1/docs/python/html/_static/websupport.js +808 -0
  174. amps-python-client-5.3.4.1/docs/python/html/chapters/advanced-topics.html +447 -0
  175. amps-python-client-5.3.4.1/docs/python/html/chapters/cpp-compiler-list.html +92 -0
  176. amps-python-client-5.3.4.1/docs/python/html/chapters/cpp-feature-table.html +156 -0
  177. amps-python-client-5.3.4.1/docs/python/html/chapters/creating-commands.html +2837 -0
  178. amps-python-client-5.3.4.1/docs/python/html/chapters/deltas.html +169 -0
  179. amps-python-client-5.3.4.1/docs/python/html/chapters/error-handling.html +746 -0
  180. amps-python-client-5.3.4.1/docs/python/html/chapters/exceptions.html +272 -0
  181. amps-python-client-5.3.4.1/docs/python/html/chapters/first-program.html +499 -0
  182. amps-python-client-5.3.4.1/docs/python/html/chapters/high-availability.html +1014 -0
  183. amps-python-client-5.3.4.1/docs/python/html/chapters/installing.html +264 -0
  184. amps-python-client-5.3.4.1/docs/python/html/chapters/introduction.html +245 -0
  185. amps-python-client-5.3.4.1/docs/python/html/chapters/moving-from-python-lite.html +118 -0
  186. amps-python-client-5.3.4.1/docs/python/html/chapters/performance-tips.html +499 -0
  187. amps-python-client-5.3.4.1/docs/python/html/chapters/queues.html +352 -0
  188. amps-python-client-5.3.4.1/docs/python/html/chapters/sow.html +381 -0
  189. amps-python-client-5.3.4.1/docs/python/html/chapters/subscriptions.html +535 -0
  190. amps-python-client-5.3.4.1/docs/python/html/chapters/utilities.html +302 -0
  191. amps-python-client-5.3.4.1/docs/python/html/genindex.html +351 -0
  192. amps-python-client-5.3.4.1/docs/python/html/index.html +380 -0
  193. amps-python-client-5.3.4.1/docs/python/html/objects.inv +0 -0
  194. amps-python-client-5.3.4.1/docs/python/html/search.html +107 -0
  195. amps-python-client-5.3.4.1/docs/python/html/searchindex.js +1 -0
  196. amps-python-client-5.3.4.1/docs/python-quickstart/doctrees/chapters/crankitup.doctree +0 -0
  197. amps-python-client-5.3.4.1/docs/python-quickstart/doctrees/chapters/equipment.doctree +0 -0
  198. amps-python-client-5.3.4.1/docs/python-quickstart/doctrees/environment.pickle +0 -0
  199. amps-python-client-5.3.4.1/docs/python-quickstart/doctrees/index.doctree +0 -0
  200. amps-python-client-5.3.4.1/docs/python-quickstart/html/.buildinfo +4 -0
  201. amps-python-client-5.3.4.1/docs/python-quickstart/html/_sources/chapters/crankitup.rst.txt +155 -0
  202. amps-python-client-5.3.4.1/docs/python-quickstart/html/_sources/chapters/equipment.rst.txt +19 -0
  203. amps-python-client-5.3.4.1/docs/python-quickstart/html/_sources/index.rst.txt +20 -0
  204. amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/ajax-loader.gif +0 -0
  205. amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/alabaster.css +699 -0
  206. amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/basic.css +632 -0
  207. amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/comment-bright.png +0 -0
  208. amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/comment-close.png +0 -0
  209. amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/comment.png +0 -0
  210. amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/custom.css +192 -0
  211. amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/custom.css.backup +161 -0
  212. amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/doctools.js +287 -0
  213. amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/down-pressed.png +0 -0
  214. amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/down.png +0 -0
  215. amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/file.png +0 -0
  216. amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/flag_logo.png +0 -0
  217. amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/flag_logo.svg +153 -0
  218. amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/jquery-3.1.0.js +10074 -0
  219. amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/jquery.js +4 -0
  220. amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/minus.png +0 -0
  221. amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/plus.png +0 -0
  222. amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/pygments.css +74 -0
  223. amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/searchtools.js +758 -0
  224. amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/underscore-1.3.1.js +999 -0
  225. amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/underscore.js +31 -0
  226. amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/up-pressed.png +0 -0
  227. amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/up.png +0 -0
  228. amps-python-client-5.3.4.1/docs/python-quickstart/html/_static/websupport.js +808 -0
  229. amps-python-client-5.3.4.1/docs/python-quickstart/html/chapters/crankitup.html +271 -0
  230. amps-python-client-5.3.4.1/docs/python-quickstart/html/chapters/equipment.html +105 -0
  231. amps-python-client-5.3.4.1/docs/python-quickstart/html/genindex.html +97 -0
  232. amps-python-client-5.3.4.1/docs/python-quickstart/html/index.html +382 -0
  233. amps-python-client-5.3.4.1/docs/python-quickstart/html/objects.inv +0 -0
  234. amps-python-client-5.3.4.1/docs/python-quickstart/html/search.html +107 -0
  235. amps-python-client-5.3.4.1/docs/python-quickstart/html/searchindex.js +1 -0
  236. amps-python-client-5.3.4.1/docs/resources/custom.css +9 -0
  237. amps-python-client-5.3.4.1/docs/resources/flag_logo.svg +153 -0
  238. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/acks.doctree +0 -0
  239. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/actions.doctree +0 -0
  240. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/amps-statistics.doctree +0 -0
  241. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/amps_expressions.doctree +0 -0
  242. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/amps_functions.doctree +0 -0
  243. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/auxiliary_modules.doctree +0 -0
  244. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/config-file-shortcuts.doctree +0 -0
  245. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/conflated_topics.doctree +0 -0
  246. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/constructing-fields.doctree +0 -0
  247. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/daemon.doctree +0 -0
  248. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/delta.doctree +0 -0
  249. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/distribution.doctree +0 -0
  250. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/enrichment.doctree +0 -0
  251. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/events.doctree +0 -0
  252. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/file_format_versions.doctree +0 -0
  253. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/glossary.doctree +0 -0
  254. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/ha.doctree +0 -0
  255. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/installing_and_starting.doctree +0 -0
  256. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/intro.doctree +0 -0
  257. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/logging.doctree +0 -0
  258. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/messageTypes.doctree +0 -0
  259. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/monitoring.doctree +0 -0
  260. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/oof.doctree +0 -0
  261. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/operation.doctree +0 -0
  262. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/pub_sub.doctree +0 -0
  263. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/queues.doctree +0 -0
  264. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/replication.doctree +0 -0
  265. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/securing.doctree +0 -0
  266. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/sow.doctree +0 -0
  267. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/sow_queries.doctree +0 -0
  268. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/spark.doctree +0 -0
  269. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/transports.doctree +0 -0
  270. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/troubleshooting.doctree +0 -0
  271. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/txlog.doctree +0 -0
  272. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/usecases.doctree +0 -0
  273. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/utilities.doctree +0 -0
  274. amps-python-client-5.3.4.1/docs/user-guide/doctrees/chapters/views.doctree +0 -0
  275. amps-python-client-5.3.4.1/docs/user-guide/doctrees/environment.pickle +0 -0
  276. amps-python-client-5.3.4.1/docs/user-guide/doctrees/index.doctree +0 -0
  277. amps-python-client-5.3.4.1/docs/user-guide/html/.buildinfo +4 -0
  278. amps-python-client-5.3.4.1/docs/user-guide/html/_images/AMPS-Queues-Intro.svg +1330 -0
  279. amps-python-client-5.3.4.1/docs/user-guide/html/_images/GeoRepl.png +0 -0
  280. amps-python-client-5.3.4.1/docs/user-guide/html/_images/HA_async_ack.png +0 -0
  281. amps-python-client-5.3.4.1/docs/user-guide/html/_images/HA_sync_ack.png +0 -0
  282. amps-python-client-5.3.4.1/docs/user-guide/html/_images/Hot-Hot-Replication.png +0 -0
  283. amps-python-client-5.3.4.1/docs/user-guide/html/_images/MessageOrdering.svg +235 -0
  284. amps-python-client-5.3.4.1/docs/user-guide/html/_images/OOF5.png +0 -0
  285. amps-python-client-5.3.4.1/docs/user-guide/html/_images/OOF6.png +0 -0
  286. amps-python-client-5.3.4.1/docs/user-guide/html/_images/OOF7.png +0 -0
  287. amps-python-client-5.3.4.1/docs/user-guide/html/_images/OOF8.png +0 -0
  288. amps-python-client-5.3.4.1/docs/user-guide/html/_images/PubSub1.svg +1 -0
  289. amps-python-client-5.3.4.1/docs/user-guide/html/_images/PubSub2.svg +1 -0
  290. amps-python-client-5.3.4.1/docs/user-guide/html/_images/SOWAndSubscribeAndReplace.svg +684 -0
  291. amps-python-client-5.3.4.1/docs/user-guide/html/_images/SOWQuery1.svg +402 -0
  292. amps-python-client-5.3.4.1/docs/user-guide/html/_images/SOWQuery2.svg +505 -0
  293. amps-python-client-5.3.4.1/docs/user-guide/html/_images/UseCaseFig1.svg +1 -0
  294. amps-python-client-5.3.4.1/docs/user-guide/html/_images/UseCaseFig2.svg +1 -0
  295. amps-python-client-5.3.4.1/docs/user-guide/html/_images/UseCaseFig3.svg +1 -0
  296. amps-python-client-5.3.4.1/docs/user-guide/html/_images/UseCaseFig4.svg +1 -0
  297. amps-python-client-5.3.4.1/docs/user-guide/html/_images/caution.png +0 -0
  298. amps-python-client-5.3.4.1/docs/user-guide/html/_images/caution.svg +25 -0
  299. amps-python-client-5.3.4.1/docs/user-guide/html/_images/chicago_group.png +0 -0
  300. amps-python-client-5.3.4.1/docs/user-guide/html/_images/delta_original_messages.png +0 -0
  301. amps-python-client-5.3.4.1/docs/user-guide/html/_images/delta_update_message.png +0 -0
  302. amps-python-client-5.3.4.1/docs/user-guide/html/_images/important.png +0 -0
  303. amps-python-client-5.3.4.1/docs/user-guide/html/_images/important.svg +25 -0
  304. amps-python-client-5.3.4.1/docs/user-guide/html/_images/inline_view_conflation.svg +1 -0
  305. amps-python-client-5.3.4.1/docs/user-guide/html/_images/paginated_subs_pub.png +0 -0
  306. amps-python-client-5.3.4.1/docs/user-guide/html/_images/paginated_subs_sub.png +0 -0
  307. amps-python-client-5.3.4.1/docs/user-guide/html/_images/queue_usage_overview.svg +627 -0
  308. amps-python-client-5.3.4.1/docs/user-guide/html/_images/replication_hub.png +0 -0
  309. amps-python-client-5.3.4.1/docs/user-guide/html/_images/replication_scenario_with_ha.png +0 -0
  310. amps-python-client-5.3.4.1/docs/user-guide/html/_images/sow_overview_1.svg +248 -0
  311. amps-python-client-5.3.4.1/docs/user-guide/html/_images/sow_overview_2.svg +183 -0
  312. amps-python-client-5.3.4.1/docs/user-guide/html/_images/sow_update_sequence.svg +1 -0
  313. amps-python-client-5.3.4.1/docs/user-guide/html/_images/tip.png +0 -0
  314. amps-python-client-5.3.4.1/docs/user-guide/html/_images/tip.svg +31 -0
  315. amps-python-client-5.3.4.1/docs/user-guide/html/_images/warning.png +0 -0
  316. amps-python-client-5.3.4.1/docs/user-guide/html/_images/warning.svg +23 -0
  317. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/acks.rst.txt +232 -0
  318. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/actions.rst.txt +111 -0
  319. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/amps-statistics.rst.txt +358 -0
  320. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/amps_expressions.rst.txt +83 -0
  321. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/amps_functions.rst.txt +11 -0
  322. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/auxiliary_modules.rst.txt +86 -0
  323. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/config-file-shortcuts.rst.txt +9 -0
  324. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/conflated_topics.rst.txt +111 -0
  325. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/constructing-fields.rst.txt +269 -0
  326. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/daemon.rst.txt +232 -0
  327. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/delta.rst.txt +556 -0
  328. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/distribution.rst.txt +186 -0
  329. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/enrichment.rst.txt +191 -0
  330. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/events.rst.txt +39 -0
  331. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/file_format_versions.rst.txt +203 -0
  332. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/glossary.rst.txt +101 -0
  333. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/ha.rst.txt +465 -0
  334. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/installing_and_starting.rst.txt +23 -0
  335. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/intro.rst.txt +116 -0
  336. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/logging.rst.txt +34 -0
  337. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/messageTypes.rst.txt +1398 -0
  338. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/monitoring.rst.txt +326 -0
  339. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/oof.rst.txt +312 -0
  340. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/operation.rst.txt +27 -0
  341. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/pub_sub.rst.txt +49 -0
  342. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/queues.rst.txt +1351 -0
  343. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/replication.rst.txt +1228 -0
  344. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/securing.rst.txt +657 -0
  345. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/sow.rst.txt +57 -0
  346. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/sow_queries.rst.txt +25 -0
  347. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/spark.rst.txt +824 -0
  348. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/transports.rst.txt +291 -0
  349. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/troubleshooting.rst.txt +517 -0
  350. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/txlog.rst.txt +62 -0
  351. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/usecases.rst.txt +21 -0
  352. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/utilities.rst.txt +62 -0
  353. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/chapters/views.rst.txt +175 -0
  354. amps-python-client-5.3.4.1/docs/user-guide/html/_sources/index.rst.txt +110 -0
  355. amps-python-client-5.3.4.1/docs/user-guide/html/_static/ajax-loader.gif +0 -0
  356. amps-python-client-5.3.4.1/docs/user-guide/html/_static/alabaster.css +695 -0
  357. amps-python-client-5.3.4.1/docs/user-guide/html/_static/basic.css +632 -0
  358. amps-python-client-5.3.4.1/docs/user-guide/html/_static/comment-bright.png +0 -0
  359. amps-python-client-5.3.4.1/docs/user-guide/html/_static/comment-close.png +0 -0
  360. amps-python-client-5.3.4.1/docs/user-guide/html/_static/comment.png +0 -0
  361. amps-python-client-5.3.4.1/docs/user-guide/html/_static/custom.css +192 -0
  362. amps-python-client-5.3.4.1/docs/user-guide/html/_static/custom.css.backup +161 -0
  363. amps-python-client-5.3.4.1/docs/user-guide/html/_static/doctools.js +287 -0
  364. amps-python-client-5.3.4.1/docs/user-guide/html/_static/down-pressed.png +0 -0
  365. amps-python-client-5.3.4.1/docs/user-guide/html/_static/down.png +0 -0
  366. amps-python-client-5.3.4.1/docs/user-guide/html/_static/file.png +0 -0
  367. amps-python-client-5.3.4.1/docs/user-guide/html/_static/flag_logo.png +0 -0
  368. amps-python-client-5.3.4.1/docs/user-guide/html/_static/flag_logo.svg +153 -0
  369. amps-python-client-5.3.4.1/docs/user-guide/html/_static/jquery-3.1.0.js +10074 -0
  370. amps-python-client-5.3.4.1/docs/user-guide/html/_static/jquery.js +4 -0
  371. amps-python-client-5.3.4.1/docs/user-guide/html/_static/minus.png +0 -0
  372. amps-python-client-5.3.4.1/docs/user-guide/html/_static/plus.png +0 -0
  373. amps-python-client-5.3.4.1/docs/user-guide/html/_static/pygments.css +74 -0
  374. amps-python-client-5.3.4.1/docs/user-guide/html/_static/searchtools.js +758 -0
  375. amps-python-client-5.3.4.1/docs/user-guide/html/_static/underscore-1.3.1.js +999 -0
  376. amps-python-client-5.3.4.1/docs/user-guide/html/_static/underscore.js +31 -0
  377. amps-python-client-5.3.4.1/docs/user-guide/html/_static/up-pressed.png +0 -0
  378. amps-python-client-5.3.4.1/docs/user-guide/html/_static/up.png +0 -0
  379. amps-python-client-5.3.4.1/docs/user-guide/html/_static/websupport.js +808 -0
  380. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/acks.html +289 -0
  381. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/actions.html +3782 -0
  382. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/amps-statistics.html +439 -0
  383. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/amps_expressions.html +1552 -0
  384. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/amps_functions.html +1626 -0
  385. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/auxiliary_modules.html +2548 -0
  386. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/config-file-shortcuts.html +508 -0
  387. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/conflated_topics.html +328 -0
  388. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/constructing-fields.html +447 -0
  389. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/daemon.html +295 -0
  390. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/delta.html +609 -0
  391. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/distribution.html +246 -0
  392. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/enrichment.html +264 -0
  393. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/events.html +449 -0
  394. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/file_format_versions.html +229 -0
  395. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/glossary.html +215 -0
  396. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/ha.html +978 -0
  397. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/installing_and_starting.html +357 -0
  398. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/intro.html +572 -0
  399. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/logging.html +972 -0
  400. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/messageTypes.html +1280 -0
  401. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/monitoring.html +718 -0
  402. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/oof.html +341 -0
  403. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/operation.html +1515 -0
  404. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/pub_sub.html +934 -0
  405. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/queues.html +1767 -0
  406. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/replication.html +1777 -0
  407. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/securing.html +697 -0
  408. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/sow.html +1038 -0
  409. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/sow_queries.html +621 -0
  410. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/spark.html +819 -0
  411. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/transports.html +352 -0
  412. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/troubleshooting.html +530 -0
  413. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/txlog.html +1013 -0
  414. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/usecases.html +288 -0
  415. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/utilities.html +133 -0
  416. amps-python-client-5.3.4.1/docs/user-guide/html/chapters/views.html +1120 -0
  417. amps-python-client-5.3.4.1/docs/user-guide/html/genindex.html +1261 -0
  418. amps-python-client-5.3.4.1/docs/user-guide/html/index.html +163 -0
  419. amps-python-client-5.3.4.1/docs/user-guide/html/objects.inv +0 -0
  420. amps-python-client-5.3.4.1/docs/user-guide/html/search.html +106 -0
  421. amps-python-client-5.3.4.1/docs/user-guide/html/searchindex.js +1 -0
  422. amps-python-client-5.3.4.1/include/ampspy_bookmarkstore.hpp +63 -0
  423. amps-python-client-5.3.4.1/include/ampspy_compat.h +63 -0
  424. amps-python-client-5.3.4.1/include/ampspy_defs.hpp +181 -0
  425. amps-python-client-5.3.4.1/include/ampspy_recoverypointadapter.hpp +52 -0
  426. amps-python-client-5.3.4.1/include/ampspy_shims.hpp +113 -0
  427. amps-python-client-5.3.4.1/include/ampspy_type_object.hpp +242 -0
  428. amps-python-client-5.3.4.1/include/ampspy_types.hpp +1139 -0
  429. amps-python-client-5.3.4.1/include/ampspyver.h +30 -0
  430. amps-python-client-5.3.4.1/index.html +66 -0
  431. amps-python-client-5.3.4.1/samples/AMPSConsolePublisher.py +59 -0
  432. amps-python-client-5.3.4.1/samples/AMPSConsoleSubscriber.py +63 -0
  433. amps-python-client-5.3.4.1/samples/AMPSFIXBuilderPublisher.py +71 -0
  434. amps-python-client-5.3.4.1/samples/AMPSFIXShredderSubscriber.py +69 -0
  435. amps-python-client-5.3.4.1/samples/AMPSNVFIXBuilderPublisher.py +71 -0
  436. amps-python-client-5.3.4.1/samples/AMPSNVFIXShredderSubscriber.py +67 -0
  437. amps-python-client-5.3.4.1/samples/AMPSPublishForReplay.py +81 -0
  438. amps-python-client-5.3.4.1/samples/AMPSQueueConsumer.py +69 -0
  439. amps-python-client-5.3.4.1/samples/AMPSQueuePublisher.py +59 -0
  440. amps-python-client-5.3.4.1/samples/AMPSSOWConsolePublisher.py +67 -0
  441. amps-python-client-5.3.4.1/samples/AMPSSOWConsoleSubscriber.py +77 -0
  442. amps-python-client-5.3.4.1/samples/AMPSSOWandSubscribeConsoleSubscriber.py +79 -0
  443. amps-python-client-5.3.4.1/samples/AMPSSOWandSubscribeWithOOF.py +108 -0
  444. amps-python-client-5.3.4.1/samples/AMPSSubscribeForReplay.py +128 -0
  445. amps-python-client-5.3.4.1/samples/AMPSUpdateForOOF.py +123 -0
  446. amps-python-client-5.3.4.1/samples/CompositeMessagePublisher.py +84 -0
  447. amps-python-client-5.3.4.1/samples/CompositeMessageSubscriber.py +87 -0
  448. amps-python-client-5.3.4.1/samples/RandomServerChooser.py +41 -0
  449. amps-python-client-5.3.4.1/samples/sample.xml +335 -0
  450. amps-python-client-5.3.4.1/setup.py +209 -0
  451. amps-python-client-5.3.4.1/setup_amps.py +94 -0
  452. amps-python-client-5.3.4.1/src/ampspy_shims.cpp +203 -0
  453. amps-python-client-5.3.4.1/src/ampspy_type_object.cpp +484 -0
  454. amps-python-client-5.3.4.1/src/authenticator.cpp +128 -0
  455. amps-python-client-5.3.4.1/src/bookmarkstore.cpp +238 -0
  456. amps-python-client-5.3.4.1/src/client.cpp +2430 -0
  457. amps-python-client-5.3.4.1/src/client_docs.h +956 -0
  458. amps-python-client-5.3.4.1/src/cmessagehandler.cpp +151 -0
  459. amps-python-client-5.3.4.1/src/command.cpp +164 -0
  460. amps-python-client-5.3.4.1/src/command_docs.h +194 -0
  461. amps-python-client-5.3.4.1/src/compositemessagebuilder.cpp +111 -0
  462. amps-python-client-5.3.4.1/src/compositemessageparser.cpp +146 -0
  463. amps-python-client-5.3.4.1/src/conflatingrecoverypointadapter.cpp +194 -0
  464. amps-python-client-5.3.4.1/src/cpp/include/amps/BlockPublishStore.hpp +2053 -0
  465. amps-python-client-5.3.4.1/src/cpp/include/amps/BlockStore.hpp +677 -0
  466. amps-python-client-5.3.4.1/src/cpp/include/amps/BookmarkStore.hpp +542 -0
  467. amps-python-client-5.3.4.1/src/cpp/include/amps/Buffer.hpp +214 -0
  468. amps-python-client-5.3.4.1/src/cpp/include/amps/CompositeMessageBuilder.hpp +174 -0
  469. amps-python-client-5.3.4.1/src/cpp/include/amps/CompositeMessageParser.hpp +151 -0
  470. amps-python-client-5.3.4.1/src/cpp/include/amps/DefaultServerChooser.hpp +162 -0
  471. amps-python-client-5.3.4.1/src/cpp/include/amps/Field.hpp +719 -0
  472. amps-python-client-5.3.4.1/src/cpp/include/amps/HAClient.hpp +370 -0
  473. amps-python-client-5.3.4.1/src/cpp/include/amps/HAClientImpl.hpp +460 -0
  474. amps-python-client-5.3.4.1/src/cpp/include/amps/HybridPublishStore.hpp +481 -0
  475. amps-python-client-5.3.4.1/src/cpp/include/amps/LoggedBookmarkStore.hpp +1255 -0
  476. amps-python-client-5.3.4.1/src/cpp/include/amps/MMapBookmarkStore.hpp +1283 -0
  477. amps-python-client-5.3.4.1/src/cpp/include/amps/MMapStoreBuffer.hpp +290 -0
  478. amps-python-client-5.3.4.1/src/cpp/include/amps/MemoryBookmarkStore.hpp +1622 -0
  479. amps-python-client-5.3.4.1/src/cpp/include/amps/MemoryPublishStore.hpp +66 -0
  480. amps-python-client-5.3.4.1/src/cpp/include/amps/MemoryStoreBuffer.hpp +244 -0
  481. amps-python-client-5.3.4.1/src/cpp/include/amps/MemorySubscriptionManager.hpp +850 -0
  482. amps-python-client-5.3.4.1/src/cpp/include/amps/Message.hpp +1819 -0
  483. amps-python-client-5.3.4.1/src/cpp/include/amps/MessageRouter.hpp +618 -0
  484. amps-python-client-5.3.4.1/src/cpp/include/amps/PublishStore.hpp +158 -0
  485. amps-python-client-5.3.4.1/src/cpp/include/amps/ReconnectDelayStrategy.hpp +106 -0
  486. amps-python-client-5.3.4.1/src/cpp/include/amps/ReconnectDelayStrategyImpl.hpp +317 -0
  487. amps-python-client-5.3.4.1/src/cpp/include/amps/RecoveryPoint.hpp +323 -0
  488. amps-python-client-5.3.4.1/src/cpp/include/amps/RecoveryPointAdapter.hpp +501 -0
  489. amps-python-client-5.3.4.1/src/cpp/include/amps/RingBookmarkStore.hpp +669 -0
  490. amps-python-client-5.3.4.1/src/cpp/include/amps/SOWRecoveryPointAdapter.hpp +490 -0
  491. amps-python-client-5.3.4.1/src/cpp/include/amps/ServerChooser.hpp +145 -0
  492. amps-python-client-5.3.4.1/src/cpp/include/amps/ServerChooserImpl.hpp +95 -0
  493. amps-python-client-5.3.4.1/src/cpp/include/amps/amps.h +775 -0
  494. amps-python-client-5.3.4.1/src/cpp/include/amps/amps_generated.h +46 -0
  495. amps-python-client-5.3.4.1/src/cpp/include/amps/amps_impl.h +204 -0
  496. amps-python-client-5.3.4.1/src/cpp/include/amps/amps_ssl.h +78 -0
  497. amps-python-client-5.3.4.1/src/cpp/include/amps/ampscrc.hpp +210 -0
  498. amps-python-client-5.3.4.1/src/cpp/include/amps/ampsplusplus.hpp +8817 -0
  499. amps-python-client-5.3.4.1/src/cpp/include/amps/ampsuri.h +84 -0
  500. amps-python-client-5.3.4.1/src/cpp/include/amps/ampsver.h +41 -0
  501. amps-python-client-5.3.4.1/src/cpp/include/amps/ampsver.h.in +41 -0
  502. amps-python-client-5.3.4.1/src/cpp/include/amps/constants.hpp +194 -0
  503. amps-python-client-5.3.4.1/src/cpp/include/amps/util.hpp +1692 -0
  504. amps-python-client-5.3.4.1/src/cpp/src/amps_protocol.c +688 -0
  505. amps-python-client-5.3.4.1/src/cpp/src/amps_protocol_generated.h +80 -0
  506. amps-python-client-5.3.4.1/src/cpp/src/amps_ssl.c +489 -0
  507. amps-python-client-5.3.4.1/src/cpp/src/atfork.c +446 -0
  508. amps-python-client-5.3.4.1/src/cpp/src/client.c +483 -0
  509. amps-python-client-5.3.4.1/src/cpp/src/makefile +92 -0
  510. amps-python-client-5.3.4.1/src/cpp/src/message.c +837 -0
  511. amps-python-client-5.3.4.1/src/cpp/src/message_generated.h +611 -0
  512. amps-python-client-5.3.4.1/src/cpp/src/tcp.c +1489 -0
  513. amps-python-client-5.3.4.1/src/cpp/src/tcps.c +1894 -0
  514. amps-python-client-5.3.4.1/src/cpp/src/transports.c +123 -0
  515. amps-python-client-5.3.4.1/src/cpp/src/unix.c +984 -0
  516. amps-python-client-5.3.4.1/src/cpp/src/uri.c +301 -0
  517. amps-python-client-5.3.4.1/src/exponentialdelaystrategy.cpp +137 -0
  518. amps-python-client-5.3.4.1/src/failedwritehandler.cpp +116 -0
  519. amps-python-client-5.3.4.1/src/fixbuilder.cpp +146 -0
  520. amps-python-client-5.3.4.1/src/fixeddelaystrategy.cpp +114 -0
  521. amps-python-client-5.3.4.1/src/fixshredder.cpp +105 -0
  522. amps-python-client-5.3.4.1/src/fixshredder_docs.h +38 -0
  523. amps-python-client-5.3.4.1/src/haclient.cpp +691 -0
  524. amps-python-client-5.3.4.1/src/haclient_docs.h +132 -0
  525. amps-python-client-5.3.4.1/src/hybridpublishstore.cpp +137 -0
  526. amps-python-client-5.3.4.1/src/hybridpublishstore_docs.h +31 -0
  527. amps-python-client-5.3.4.1/src/memorybookmarkstore.cpp +373 -0
  528. amps-python-client-5.3.4.1/src/memorybookmarkstore_docs.h +39 -0
  529. amps-python-client-5.3.4.1/src/memorypublishstore.cpp +160 -0
  530. amps-python-client-5.3.4.1/src/memorypublishstore_docs.h +32 -0
  531. amps-python-client-5.3.4.1/src/message.cpp +765 -0
  532. amps-python-client-5.3.4.1/src/message_docs.h +306 -0
  533. amps-python-client-5.3.4.1/src/messagestream.cpp +623 -0
  534. amps-python-client-5.3.4.1/src/messagestream_docs.h +45 -0
  535. amps-python-client-5.3.4.1/src/mmapbookmarkstore.cpp +422 -0
  536. amps-python-client-5.3.4.1/src/nvfixbuilder.cpp +160 -0
  537. amps-python-client-5.3.4.1/src/nvfixbuilder_docs.h +33 -0
  538. amps-python-client-5.3.4.1/src/nvfixshredder.cpp +99 -0
  539. amps-python-client-5.3.4.1/src/nvfixshredder_docs.h +39 -0
  540. amps-python-client-5.3.4.1/src/publishstore.cpp +183 -0
  541. amps-python-client-5.3.4.1/src/raw_wrapper.cpp +756 -0
  542. amps-python-client-5.3.4.1/src/reason.cpp +71 -0
  543. amps-python-client-5.3.4.1/src/recoverypoint.cpp +135 -0
  544. amps-python-client-5.3.4.1/src/recoverypointadapter.cpp +171 -0
  545. amps-python-client-5.3.4.1/src/ringbookmarkstore.cpp +360 -0
  546. amps-python-client-5.3.4.1/src/serverchooser.cpp +245 -0
  547. amps-python-client-5.3.4.1/src/serverchooser_docs.h +39 -0
  548. amps-python-client-5.3.4.1/src/sowrecoverypointadapter.cpp +248 -0
  549. amps-python-client-5.3.4.1/src/store.cpp +62 -0
  550. amps-python-client-5.3.4.1/src/versioninfo.cpp +175 -0
@@ -0,0 +1,1622 @@
1
+ ////////////////////////////////////////////////////////////////////////////
2
+ //
3
+ // Copyright (c) 2010-2023 60East Technologies Inc., All Rights Reserved.
4
+ //
5
+ // This computer software is owned by 60East Technologies Inc. and is
6
+ // protected by U.S. copyright laws and other laws and by international
7
+ // treaties. This computer software is furnished by 60East Technologies
8
+ // Inc. pursuant to a written license agreement and may be used, copied,
9
+ // transmitted, and stored only in accordance with the terms of such
10
+ // license agreement and with the inclusion of the above copyright notice.
11
+ // This computer software or any other copies thereof may not be provided
12
+ // or otherwise made available to any other person.
13
+ //
14
+ // U.S. Government Restricted Rights. This computer software: (a) was
15
+ // developed at private expense and is in all respects the proprietary
16
+ // information of 60East Technologies Inc.; (b) was not developed with
17
+ // government funds; (c) is a trade secret of 60East Technologies Inc.
18
+ // for all purposes of the Freedom of Information Act; and (d) is a
19
+ // commercial item and thus, pursuant to Section 12.212 of the Federal
20
+ // Acquisition Regulations (FAR) and DFAR Supplement Section 227.7202,
21
+ // Government's use, duplication or disclosure of the computer software
22
+ // is subject to the restrictions set forth by 60East Technologies Inc..
23
+ //
24
+ ////////////////////////////////////////////////////////////////////////////
25
+
26
+ #ifndef _MEMORYBOOKMARKSTORE_H_
27
+ #define _MEMORYBOOKMARKSTORE_H_
28
+
29
+ #include <amps/BookmarkStore.hpp>
30
+ #include <amps/Field.hpp>
31
+ #include <amps/Message.hpp>
32
+ #include <amps/RecoveryPoint.hpp>
33
+ #include <amps/RecoveryPointAdapter.hpp>
34
+ #include <map>
35
+ #include <sstream>
36
+ #include <vector>
37
+ #include <stdlib.h>
38
+ #include <assert.h>
39
+
40
+ #define AMPS_MIN_BOOKMARK_LEN 3
41
+ #define AMPS_INITIAL_MEMORY_BOOKMARK_SIZE 16384UL
42
+
43
+ /// \file MemoryBookmarkStore.hpp
44
+ /// \brief Provides AMPS::MemoryBookmarkStore, a bookmark store that holds
45
+ /// bookmarks in memory. This bookmark store protects against connectivity
46
+ /// failures.
47
+
48
+ namespace AMPS
49
+ {
50
+
51
+ ///
52
+ /// A BookmarkStoreImpl implementation that stores bookmarks in memory. This
53
+ /// store protects against connectivity failures. This store does not
54
+ /// persist the bookmark store, so this store cannot be used to resume
55
+ /// subscriptions after application restart.
56
+ class MemoryBookmarkStore : public BookmarkStoreImpl
57
+ {
58
+ protected:
59
+ class Subscription
60
+ {
61
+ public:
62
+ typedef std::map<Message::Field, size_t, Message::Field::FieldHash> RecoveryMap;
63
+ typedef std::map<amps_uint64_t, amps_uint64_t> PublisherMap;
64
+ typedef std::map<Message::Field, size_t, Message::Field::FieldHash>::iterator
65
+ RecoveryIterator;
66
+ typedef std::map<amps_uint64_t, amps_uint64_t>::iterator PublisherIterator;
67
+
68
+ // Start sequence at 1 so that 0 can be used during file subclasses
69
+ // recovery as an indicator that a message wasn't logged because
70
+ // isDiscarded() was true.
71
+ Subscription(MemoryBookmarkStore* store_, const Message::Field& id_)
72
+ : _current(1), _currentBase(0), _least(1), _leastBase(0)
73
+ , _recoveryMin(AMPS_UNSET_INDEX), _recoveryBase(AMPS_UNSET_INDEX)
74
+ , _recoveryMax(AMPS_UNSET_INDEX), _recoveryMaxBase(AMPS_UNSET_INDEX)
75
+ , _entriesLength(AMPS_INITIAL_MEMORY_BOOKMARK_SIZE), _entries(NULL)
76
+ , _store(store_)
77
+ {
78
+ // Need our own memory for the sub id
79
+ _id.deepCopy(id_);
80
+ _store->resize(_id, (char**)&_entries,
81
+ sizeof(Entry)*AMPS_INITIAL_MEMORY_BOOKMARK_SIZE, false);
82
+ setLastPersistedToEpoch();
83
+ }
84
+
85
+ ~Subscription()
86
+ {
87
+ Lock<Mutex> guard(_subLock);
88
+ if (_entries)
89
+ {
90
+ for (size_t i = 0; i < _entriesLength; ++i)
91
+ {
92
+ _entries[i]._val.clear();
93
+ }
94
+ // resize to 0 will free _entries
95
+ _store->resize(_id, (char**)&_entries, 0);
96
+ }
97
+ _id.clear();
98
+ _recent.clear();
99
+ _lastPersisted.clear();
100
+ _recentList.clear();
101
+ _range.clear();
102
+ _recoveryTimestamp.clear();
103
+ }
104
+
105
+ size_t log(const Message::Field& bookmark_)
106
+ {
107
+ if (bookmark_ == AMPS_BOOKMARK_NOW)
108
+ {
109
+ return 0;
110
+ }
111
+ Lock<Mutex> guard(_subLock);
112
+ // Either relog the recovery or log it
113
+ size_t index = recover(bookmark_, true);
114
+ if (index == AMPS_UNSET_INDEX)
115
+ {
116
+ // Check for wrap
117
+ if (_current >= _entriesLength)
118
+ {
119
+ _current = 0;
120
+ _currentBase += _entriesLength;
121
+ }
122
+ // Check for resize
123
+ // If list is too small, double it
124
+ if ((_current == _least && _leastBase < _currentBase) ||
125
+ (_current == _recoveryMin && _recoveryBase < _currentBase))
126
+ {
127
+ if (!_store->resize(_id, (char**)&_entries,
128
+ sizeof(Entry) * _entriesLength * 2))
129
+ {
130
+ //Try again
131
+ return log(bookmark_);
132
+ }
133
+ // Length was doubled
134
+ _entriesLength *= 2;
135
+ }
136
+
137
+ // Add this entry to the end of our list
138
+ /*
139
+ if (bookmark_ == AMPS_BOOKMARK_NOW)
140
+ {
141
+ // Save a now timestamp bookmark
142
+ char* nowTimestamp = new char[AMPS_TIMESTAMP_LEN];
143
+ struct tm timeInfo;
144
+ time_t now;
145
+ time(&now);
146
+ #ifdef _WIN32
147
+ gmtime_s(&timeInfo, &now);
148
+ #else
149
+ gmtime_r(&now, &timeInfo);
150
+ #endif
151
+ strftime(nowTimestamp, AMPS_TIMESTAMP_LEN,
152
+ "%Y%m%dT%H%M%S", &timeInfo);
153
+ nowTimestamp[AMPS_TIMESTAMP_LEN-1] = 'Z';
154
+ _entries[_current]._val.assign(nowTimestamp,
155
+ AMPS_TIMESTAMP_LEN);
156
+ _entries[_current]._active = false;
157
+ index = _current++;
158
+ return index + _currentBase;
159
+ }
160
+ else
161
+ */
162
+ {
163
+ // Is this an attempt at a range?
164
+ if (!BookmarkRange::isRange(bookmark_))
165
+ {
166
+ _entries[_current]._val.deepCopy(bookmark_);
167
+ }
168
+ else
169
+ {
170
+ // Deep copy of the range is saved
171
+ _range.set(bookmark_);
172
+ // Stricter check on range syntax
173
+ if (!_range.isValid())
174
+ {
175
+ throw CommandException("Invalid bookmark range specified.");
176
+ }
177
+ _store->updateAdapter(this);
178
+ if (!_range.isStartInclusive())
179
+ {
180
+ // Put it in our publishers map
181
+ amps_uint64_t publisher, sequence;
182
+ std::vector<Field> bmList = Field::parseBookmarkList(_range.getStart());
183
+ for (std::vector<Field>::iterator bkmk = bmList.begin(); bkmk != bmList.end(); ++bkmk)
184
+ {
185
+ parseBookmark(*bkmk, publisher, sequence);
186
+ if (publisher != (amps_uint64_t)0)
187
+ {
188
+ // Compare it to our publishers map
189
+ PublisherIterator pub = _publishers.find(publisher);
190
+ if (pub == _publishers.end() || pub->second < sequence)
191
+ {
192
+ _publishers[publisher] = sequence;
193
+ }
194
+ }
195
+ }
196
+ }
197
+ // Don't actually log a range
198
+ return 0;
199
+ }
200
+ }
201
+ _entries[_current]._active = true;
202
+ index = _current++;
203
+ }
204
+ return index + _currentBase;
205
+ }
206
+
207
+ bool discard(size_t index_)
208
+ {
209
+ Lock<Mutex> guard(_subLock);
210
+ return _discard(index_);
211
+ }
212
+
213
+ bool discard(const Message::Field& bookmark_)
214
+ {
215
+ // These are discarded when logged or not logged
216
+ if (bookmark_ == AMPS_BOOKMARK_NOW)
217
+ {
218
+ return false;
219
+ }
220
+ Lock<Mutex> guard(_subLock);
221
+ size_t search = _least;
222
+ size_t searchBase = _leastBase;
223
+ size_t searchMax = _current;
224
+ size_t searchMaxBase = _currentBase;
225
+ if (_least + _leastBase == _current + _currentBase)
226
+ {
227
+ if (_recoveryMin != AMPS_UNSET_INDEX)
228
+ {
229
+ search = _recoveryMin;
230
+ searchBase = _recoveryBase;
231
+ searchMax = _recoveryMax;
232
+ searchMaxBase = _recoveryMaxBase;
233
+ }
234
+ else // Store is empty, so nothing to do
235
+ {
236
+ return false;
237
+ }
238
+ }
239
+ assert(searchMax != AMPS_UNSET_INDEX);
240
+ assert(searchMaxBase != AMPS_UNSET_INDEX);
241
+ assert(search != AMPS_UNSET_INDEX);
242
+ assert(searchBase != AMPS_UNSET_INDEX);
243
+ // Search while we don't find the provided bookmark and we're in valid range
244
+ while (search + searchBase < searchMax + searchMaxBase)
245
+ {
246
+ if (_entries[search]._val == bookmark_)
247
+ {
248
+ return _discard(search + searchBase);
249
+ }
250
+ if (++search == _entriesLength)
251
+ {
252
+ // Least has now loooped around
253
+ searchBase += _entriesLength;
254
+ search = 0;
255
+ }
256
+ }
257
+ return false;
258
+ }
259
+
260
+ // Get sequence number from a Field that is a bookmark
261
+ static void parseBookmark(const Message::Field& field_,
262
+ amps_uint64_t& publisherId_,
263
+ amps_uint64_t& sequenceNumber_)
264
+ {
265
+ Message::Field::parseBookmark(field_, publisherId_, sequenceNumber_);
266
+ }
267
+
268
+ // Check to see if this message is older than the most recent one seen,
269
+ // and if it is, check if it discarded.
270
+ bool isDiscarded(const Message::Field& bookmark_)
271
+ {
272
+ Lock<Mutex> guard(_subLock);
273
+ if (BookmarkRange::isRange(bookmark_))
274
+ {
275
+ return false;
276
+ }
277
+ // Check if we've already recovered this bookmark
278
+ size_t recoveredIdx = recover(bookmark_, false);
279
+
280
+ amps_uint64_t publisher, sequence;
281
+ parseBookmark(bookmark_, publisher, sequence);
282
+ // Compare it to our publishers map
283
+ PublisherIterator pub = _publishers.find(publisher);
284
+ if (pub == _publishers.end() || pub->second < sequence)
285
+ {
286
+ _publishers[publisher] = sequence;
287
+ if (recoveredIdx == AMPS_UNSET_INDEX)
288
+ {
289
+ return false;
290
+ }
291
+ }
292
+ if (recoveredIdx != AMPS_UNSET_INDEX)
293
+ {
294
+ if (!_entries[recoveredIdx]._active)
295
+ {
296
+ _recovered.erase(bookmark_);
297
+ return true;
298
+ }
299
+ return false;
300
+ }
301
+ // During recovery, we don't really care if it's been discarded
302
+ // or not. We just want _publishers updated. No need for the
303
+ // costly linear search.
304
+ if (_store->_recovering)
305
+ {
306
+ return false;
307
+ }
308
+ // During failure and recovery scenarios, we'll see out of order
309
+ // bookmarks arrive, either because (a) we're replaying or (b)
310
+ // a publisher has cut over, and we've cut over to a new server.
311
+ // Scan the list to see if we have a match.
312
+ size_t base = _leastBase;
313
+ for (size_t i = _least; i + base < _current + _currentBase; i++)
314
+ {
315
+ if ( i >= _entriesLength )
316
+ {
317
+ i = 0;
318
+ base = _currentBase;
319
+ }
320
+ if (_entries[i]._val == bookmark_)
321
+ {
322
+ return !_entries[i]._active;
323
+ }
324
+ }
325
+
326
+ return true; // message is totally discarded
327
+ }
328
+
329
+ bool empty(void) const
330
+ {
331
+ if (_least == AMPS_UNSET_INDEX ||
332
+ ((_least + _leastBase) == (_current + _currentBase) &&
333
+ _recoveryMin == AMPS_UNSET_INDEX))
334
+ {
335
+ return true;
336
+ }
337
+ return false;
338
+ }
339
+
340
+ void updateMostRecent()
341
+ {
342
+ Lock<Mutex> guard(_subLock);
343
+ _updateMostRecent();
344
+ }
345
+
346
+ const BookmarkRange& getRange() const
347
+ {
348
+ return _range;
349
+ }
350
+
351
+ Message::Field getMostRecentList(bool usePublishersList_ = true)
352
+ {
353
+ Lock<Mutex> guard(_subLock);
354
+ bool useLastPersisted = !_lastPersisted.empty() &&
355
+ _lastPersisted.len() > 1;
356
+ // when this is called, we'll take a moment to update the list
357
+ // of things recovered,
358
+ // so we don't accidentally log anything we ought not to.
359
+ _updateMostRecent();
360
+ bool useRecent = !_recent.empty() && _recent.len() > 1;
361
+ amps_uint64_t lastPublisher = 0;
362
+ amps_uint64_t lastSeq = 0;
363
+ amps_uint64_t recentPublisher = 0;
364
+ amps_uint64_t recentSeq = 0;
365
+ if (useLastPersisted)
366
+ {
367
+ parseBookmark(_lastPersisted, lastPublisher, lastSeq);
368
+ }
369
+ if (useRecent)
370
+ {
371
+ parseBookmark(_recent, recentPublisher, recentSeq);
372
+ if (empty() && useLastPersisted)
373
+ {
374
+ useRecent = false;
375
+ }
376
+ else
377
+ {
378
+ if (useLastPersisted && lastPublisher == recentPublisher)
379
+ {
380
+ if (lastSeq <= recentSeq)
381
+ {
382
+ useRecent = false;
383
+ }
384
+ else
385
+ {
386
+ useLastPersisted = false;
387
+ }
388
+ }
389
+ }
390
+ }
391
+ // Set size for all bookmarks that will be used
392
+ size_t totalLen = (useLastPersisted ? _lastPersisted.len() + 1 : 0);
393
+ if (useRecent)
394
+ {
395
+ totalLen += _recent.len() + 1;
396
+ }
397
+ // If we don't have a non-EPOCH persisted ack and we don't have a
398
+ // non-EPOCH most recent bookmark, OR we have a range
399
+ // we can build a list based on all the publishers instead.
400
+ if (usePublishersList_
401
+ && ((!useLastPersisted && !useRecent)
402
+ || _lastPersisted == AMPS_BOOKMARK_EPOCH))
403
+ {
404
+ std::ostringstream os;
405
+ for (PublisherIterator pub = _publishers.begin();
406
+ pub != _publishers.end(); ++pub)
407
+ {
408
+ if (pub->first == 0 && pub->second == 0)
409
+ {
410
+ continue;
411
+ }
412
+ if (pub->first == recentPublisher && recentSeq < pub->second)
413
+ {
414
+ os << recentPublisher << '|' << recentSeq << "|,";
415
+ }
416
+ else
417
+ {
418
+ os << pub->first << '|' << pub->second << "|,";
419
+ }
420
+ }
421
+ std::string recent = os.str();
422
+ totalLen = recent.length();
423
+ if (!recent.empty())
424
+ {
425
+ if (!_recoveryTimestamp.empty())
426
+ {
427
+ totalLen += _recoveryTimestamp.len();
428
+ recent += std::string(_recoveryTimestamp);
429
+ }
430
+ else
431
+ {
432
+ // Remove trailing ,
433
+ recent.erase(--totalLen);
434
+ }
435
+ // Reset _recentList to new value and return it
436
+ _recentList.clear();
437
+ _recentList = Message::Field(recent).deepCopy();
438
+ if (_range.isValid())
439
+ {
440
+ if (_range.getStart() != recent
441
+ && _recentList != AMPS_BOOKMARK_EPOCH)
442
+ {
443
+ _range.replaceStart(_recentList, true);
444
+ }
445
+ else if (_range.isStartInclusive())
446
+ {
447
+ amps_uint64_t publisher, sequence;
448
+ parseBookmark(_range.getStart(), publisher,
449
+ sequence);
450
+ PublisherIterator pub = _publishers.find(publisher);
451
+ if (pub != _publishers.end()
452
+ && pub->second >= sequence)
453
+ {
454
+ _range.makeStartExclusive();
455
+ }
456
+ }
457
+ return _range;
458
+ }
459
+ return _recentList;
460
+ }
461
+ if (_range.isValid())
462
+ {
463
+ return _range;
464
+ }
465
+ }
466
+ if (!_recoveryTimestamp.empty() && !_range.isValid())
467
+ {
468
+ totalLen += _recoveryTimestamp.len() + 1;
469
+ }
470
+ // If we have nothing discarded, return EPOCH
471
+ if (totalLen == 0
472
+ || (_recent.len() < 2 && !empty()))
473
+ {
474
+ if (_range.isValid())
475
+ {
476
+ return _range;
477
+ }
478
+ if (!useRecent)
479
+ {
480
+ return Message::Field(AMPS_BOOKMARK_EPOCH);
481
+ }
482
+ _setLastPersistedToEpoch();
483
+ return _lastPersisted;
484
+ }
485
+ // Remove the trailing , from the length
486
+ totalLen -= 1;
487
+ char* field = new char[totalLen];
488
+ size_t len = 0;
489
+ if (useRecent)
490
+ {
491
+ len = _recent.len();
492
+ memcpy(field, _recent.data(), len);
493
+ if (len < totalLen)
494
+ {
495
+ field[len++] = ',';
496
+ }
497
+ }
498
+ if (useLastPersisted)
499
+ {
500
+ memcpy(field + len, _lastPersisted.data(), _lastPersisted.len());
501
+ len += _lastPersisted.len();
502
+ if (len < totalLen)
503
+ {
504
+ field[len++] = ',';
505
+ }
506
+ }
507
+ if (!_recoveryTimestamp.empty() && !_range.isValid())
508
+ {
509
+ memcpy(field + len, _recoveryTimestamp.data(),
510
+ _recoveryTimestamp.len());
511
+ // If more is to be written after this, uncomment the following
512
+ //len += _lastPersisted.len();
513
+ //if (len < totalLen) field[len++] = ',';
514
+ }
515
+ // _recentList clear will delete[] current buffer and assign will get cleared
516
+ _recentList.clear();
517
+ _recentList.assign(field, totalLen);
518
+ if (_range.isValid())
519
+ {
520
+ if (_recentList != AMPS_BOOKMARK_EPOCH)
521
+ {
522
+ if (_range.getStart() != _recentList)
523
+ {
524
+ _range.replaceStart(_recentList, true);
525
+ }
526
+ else if (_range.isStartInclusive())
527
+ {
528
+ amps_uint64_t publisher, sequence;
529
+ parseBookmark(_range.getStart(), publisher,
530
+ sequence);
531
+ PublisherIterator pub = _publishers.find(publisher);
532
+ if (pub != _publishers.end()
533
+ && pub->second >= sequence)
534
+ {
535
+ _range.makeStartExclusive();
536
+ }
537
+ }
538
+ }
539
+ return _range;
540
+ }
541
+ return _recentList;
542
+ }
543
+
544
+ Message::Field getMostRecent(bool update_ = false)
545
+ {
546
+ Lock<Mutex> guard(_subLock);
547
+ // Return the same as last time if nothing's changed
548
+ // _recent is the most recent bookmark.
549
+ if (update_ && _store->_recentChanged)
550
+ {
551
+ _updateMostRecent();
552
+ }
553
+ if (_recent.empty())
554
+ {
555
+ return Message::Field(AMPS_BOOKMARK_EPOCH);
556
+ }
557
+ else
558
+ {
559
+ return _recent;
560
+ }
561
+ }
562
+
563
+ Message::Field getLastPersisted()
564
+ {
565
+ Lock<Mutex> guard(_subLock);
566
+ return _lastPersisted;
567
+ }
568
+
569
+ void setMostRecent(const Message::Field& recent_)
570
+ {
571
+ _recent.clear();
572
+ _recent.deepCopy(recent_);
573
+ }
574
+
575
+ void setRecoveryTimestamp(const char* recoveryTimestamp_,
576
+ size_t len_ = 0)
577
+ {
578
+ _recoveryTimestamp.clear();
579
+ size_t len = (len_ == 0) ? AMPS_TIMESTAMP_LEN : len_;
580
+ char* ts = new char[len];
581
+ memcpy((void*)ts, (const void*)recoveryTimestamp_, len);
582
+ _recoveryTimestamp.assign(ts, len);
583
+ }
584
+
585
+ void moveEntries(char* old_, char* new_, size_t newSize_)
586
+ {
587
+ size_t least = _least;
588
+ size_t leastBase = _leastBase;
589
+ if (_recoveryMin != AMPS_UNSET_INDEX)
590
+ {
591
+ least = _recoveryMin;
592
+ leastBase = _recoveryBase;
593
+ }
594
+ // First check if we grew in place, if so, just move current after least
595
+ if (old_ == new_)
596
+ {
597
+ if (newSize_ - (sizeof(Entry)*_entriesLength) > sizeof(Entry)*least)
598
+ {
599
+ memcpy(new_ + (sizeof(Entry)*_entriesLength),
600
+ old_, (sizeof(Entry)*least));
601
+ // Clear the beginning where those entries were
602
+ memset(old_, 0, sizeof(Entry)*least);
603
+ }
604
+ else // We have to use an intermediate buffer
605
+ {
606
+ Entry* buffer = new Entry[least];
607
+ memcpy((void*)buffer, (void*)old_, sizeof(Entry)*least);
608
+ //Put the beginning entries at the start of the new buffer
609
+ memcpy((void*)new_, (void*)((char*)old_ + (sizeof(Entry)*least)),
610
+ (_entriesLength - least)*sizeof(Entry));
611
+ //Put the end entries after the beginning entries
612
+ memcpy((void*)((char*)new_ + ((_entriesLength - least)*sizeof(Entry))),
613
+ (void*)buffer, least * sizeof(Entry));
614
+ // Least is now at 0 so base must be increased
615
+ leastBase += least;
616
+ least = 0;
617
+ delete [] buffer;
618
+ }
619
+ }
620
+ else
621
+ {
622
+ //Put the beginning entries at the start of the new buffer
623
+ memcpy((void*)new_, (void*)((char*)old_ + (sizeof(Entry)*least)),
624
+ (_entriesLength - least)*sizeof(Entry));
625
+ //Put the end entries after the beginning entries
626
+ memcpy((void*)((char*)new_ + ((_entriesLength - least)*sizeof(Entry))),
627
+ (void*)old_, least * sizeof(Entry));
628
+ // Least is now at 0 so base must be increased
629
+ leastBase += least;
630
+ least = 0;
631
+ }
632
+ if (_recoveryMin != AMPS_UNSET_INDEX)
633
+ {
634
+ _least = least + (_least + _leastBase) - (_recoveryMin + _recoveryBase);
635
+ _recoveryMax = least + (_recoveryMax + _recoveryMaxBase) -
636
+ (_recoveryMin + _recoveryBase);
637
+ _recoveryMaxBase = leastBase;
638
+ _recoveryMin = least;
639
+ _recoveryBase = leastBase;
640
+ }
641
+ else
642
+ {
643
+ _least = least;
644
+ }
645
+ _leastBase = leastBase;
646
+ // Current is now after everything and using the same base
647
+ _currentBase = _leastBase;
648
+ _current = least + _entriesLength;
649
+ }
650
+
651
+ inline size_t getOldestBookmarkSeq()
652
+ {
653
+ Lock<Mutex> guard(_subLock);
654
+ // If there is nothing in the store, return -1, otherwise return lowest
655
+ return ((_least + _leastBase) == (_current + _currentBase)) ? AMPS_UNSET_INDEX :
656
+ _least + _leastBase;
657
+ }
658
+
659
+ bool lastPersisted(const Message::Field& bookmark_)
660
+ {
661
+ // These shouldn't be persisted
662
+ if (bookmark_ == AMPS_BOOKMARK_NOW
663
+ || BookmarkRange::isRange(bookmark_))
664
+ {
665
+ return false;
666
+ }
667
+ Lock<Mutex> guard(_subLock);
668
+ return _setLastPersisted(bookmark_);
669
+ }
670
+
671
+ bool _setLastPersisted(const Message::Field& bookmark_)
672
+ {
673
+ if (!_lastPersisted.empty())
674
+ {
675
+ amps_uint64_t publisher, publisher_lastPersisted;
676
+ amps_uint64_t sequence, sequence_lastPersisted;
677
+ parseBookmark(bookmark_, publisher, sequence);
678
+ parseBookmark(_lastPersisted, publisher_lastPersisted,
679
+ sequence_lastPersisted);
680
+ if (publisher == publisher_lastPersisted &&
681
+ sequence <= sequence_lastPersisted)
682
+ {
683
+ return false;
684
+ }
685
+ }
686
+ // deepCopy will clear what's in _lastPersisted
687
+ _lastPersisted.deepCopy(bookmark_);
688
+ _store->_recentChanged = true;
689
+ _recoveryTimestamp.clear();
690
+ return true;
691
+ }
692
+
693
+ Message::Field lastPersisted(size_t bookmark_)
694
+ {
695
+ Lock<Mutex> guard(_subLock);
696
+ Message::Field& bookmark = _entries[bookmark_]._val;
697
+ // These shouldn't be persisted
698
+ if (bookmark == AMPS_BOOKMARK_NOW
699
+ || BookmarkRange::isRange(bookmark))
700
+ {
701
+ return bookmark;
702
+ }
703
+ _setLastPersisted(bookmark);
704
+ return bookmark;
705
+ }
706
+
707
+ // Returns the index of the recovered item, either the index where it
708
+ // was first stored prior to getMostRecent, or the new index if it is
709
+ // relogged either because this is called from log() or because it was
710
+ // not active but also not persisted.
711
+ size_t recover(const Message::Field& bookmark_, bool relogIfNotDiscarded)
712
+ {
713
+ size_t retVal = AMPS_UNSET_INDEX;
714
+ if (_recovered.empty() || _recoveryBase == AMPS_UNSET_INDEX)
715
+ {
716
+ return retVal;
717
+ }
718
+ // Check if this is a recovered bookmark.
719
+ // If so, copy the existing one to the new location
720
+ RecoveryIterator item = _recovered.find(bookmark_);
721
+ if (item != _recovered.end())
722
+ {
723
+ size_t seqNo = item->second;
724
+ size_t index = (seqNo - _recoveryBase) % _entriesLength;
725
+ // If we only have recovery entries and isDiscarded is
726
+ // checking on an already discarded entry, update recent.
727
+ if (_least + _leastBase == _current + _currentBase &&
728
+ !_entries[index]._active)
729
+ {
730
+ _store->_recentChanged = true;
731
+ _recent.clear();
732
+ _recent = _entries[index]._val.deepCopy();
733
+ retVal = moveEntry(index);
734
+ if (retVal == AMPS_UNSET_INDEX)
735
+ {
736
+ recover(bookmark_, relogIfNotDiscarded);
737
+ }
738
+ _least = _current;
739
+ _leastBase = _currentBase;
740
+ }
741
+ else if (!_entries[index]._active || relogIfNotDiscarded)
742
+ {
743
+ retVal = moveEntry(index);
744
+ if (retVal == AMPS_UNSET_INDEX)
745
+ {
746
+ recover(bookmark_, relogIfNotDiscarded);
747
+ }
748
+ }
749
+ else
750
+ {
751
+ return index;
752
+ }
753
+ _recovered.erase(item);
754
+ if (_recovered.empty())
755
+ {
756
+ _recoveryMin = AMPS_UNSET_INDEX;
757
+ _recoveryBase = AMPS_UNSET_INDEX;
758
+ _recoveryMax = AMPS_UNSET_INDEX;
759
+ _recoveryMaxBase = AMPS_UNSET_INDEX;
760
+ }
761
+ else if (index == _recoveryMin)
762
+ {
763
+ while (_entries[_recoveryMin]._val.empty() &&
764
+ (_recoveryMin + _recoveryBase) < (_recoveryMax + _recoveryMaxBase))
765
+ {
766
+ if (++_recoveryMin == _entriesLength)
767
+ {
768
+ _recoveryMin = 0;
769
+ _recoveryBase += _entriesLength;
770
+ }
771
+ }
772
+ }
773
+ }
774
+ return retVal;
775
+ }
776
+
777
+ // Return the id of this Subscription
778
+ Message::Field id() const
779
+ {
780
+ return _id;
781
+ }
782
+
783
+ struct Entry
784
+ {
785
+ Message::Field _val; //16
786
+ bool _active; //17
787
+ char _padding[32 - sizeof(Message::Field) - sizeof(bool)]; //32
788
+
789
+ Entry() : _active(false)
790
+ {
791
+ ;
792
+ }
793
+ };
794
+
795
+ struct EntryHash
796
+ {
797
+ Field::FieldHash _hasher;
798
+
799
+ size_t operator()(const Entry* entryPtr_) const
800
+ {
801
+ return _hasher(entryPtr_->_val);
802
+ }
803
+
804
+ bool operator()(const Entry* lhsPtr_, const Entry* rhsPtr_) const
805
+ {
806
+ return _hasher(lhsPtr_->_val, rhsPtr_->_val);
807
+ }
808
+ };
809
+
810
+ //typedef std::set<Entry*, EntryHash> EntryPtrList;
811
+ typedef std::vector<Entry*> EntryPtrList;
812
+
813
+ void getRecoveryEntries(EntryPtrList& list_)
814
+ {
815
+ if (_recoveryMin == AMPS_UNSET_INDEX ||
816
+ _recoveryMax == AMPS_UNSET_INDEX)
817
+ {
818
+ return;
819
+ }
820
+ size_t base = _recoveryBase;
821
+ size_t max = _recoveryMax + _recoveryMaxBase;
822
+ for (size_t i = _recoveryMin; i + base < max; ++i)
823
+ {
824
+ if (i == _entriesLength)
825
+ {
826
+ i = 0;
827
+ base = _recoveryMaxBase;
828
+ }
829
+ //list_.insert(&(_entries[i]));
830
+ list_.push_back(&(_entries[i]));
831
+ }
832
+ return;
833
+ }
834
+
835
+ void getActiveEntries(EntryPtrList& list_)
836
+ {
837
+ size_t base = _leastBase;
838
+ for (size_t i = _least; i + base < _current + _currentBase; ++i)
839
+ {
840
+ if (i >= _entriesLength)
841
+ {
842
+ i = 0;
843
+ base = _currentBase;
844
+ }
845
+ //list_.insert(&(_entries[i]));
846
+ list_.push_back(&(_entries[i]));
847
+ }
848
+ return;
849
+ }
850
+
851
+ Entry* getEntryByIndex(size_t index_)
852
+ {
853
+ Lock<Mutex> guard(_subLock);
854
+ size_t base = (_recoveryBase == AMPS_UNSET_INDEX ||
855
+ index_ >= _least + _leastBase)
856
+ ? _leastBase : _recoveryBase;
857
+ // Return NULL if not a valid index
858
+ size_t min = (_recoveryMin == AMPS_UNSET_INDEX ?
859
+ _least + _leastBase :
860
+ _recoveryMin + _recoveryBase);
861
+ if (index_ >= _current + _currentBase || index_ < min)
862
+ {
863
+ return NULL;
864
+ }
865
+ return &(_entries[(index_ - base) % _entriesLength]);
866
+ }
867
+
868
+ void justRecovered()
869
+ {
870
+ Lock<Mutex> guard(_subLock);
871
+ _updateMostRecent();
872
+ EntryPtrList list;
873
+ getRecoveryEntries(list);
874
+ setPublishersToDiscarded(&list, &_publishers);
875
+ }
876
+
877
+ void setPublishersToDiscarded(EntryPtrList* recovered_,
878
+ PublisherMap* publishers_)
879
+ {
880
+ // Need to reset publishers to only have up to the last
881
+ // discarded sequence number. Messages that were in transit
882
+ // during previous run but not discarded should be considered
883
+ // new and not duplicate after a restart/recovery.
884
+ for (EntryPtrList::iterator i = recovered_->begin();
885
+ i != recovered_->end(); ++i)
886
+ {
887
+ if ((*i)->_val.empty())
888
+ {
889
+ continue;
890
+ }
891
+ amps_uint64_t publisher = (amps_uint64_t)0;
892
+ amps_uint64_t sequence = (amps_uint64_t)0;
893
+ parseBookmark((*i)->_val, publisher, sequence);
894
+ if (publisher && sequence && (*i)->_active &&
895
+ (*publishers_)[publisher] >= sequence)
896
+ {
897
+ (*publishers_)[publisher] = sequence - 1;
898
+ }
899
+ }
900
+ }
901
+
902
+ void clearLastPersisted()
903
+ {
904
+ Lock<Mutex> guard(_subLock);
905
+ _lastPersisted.clear();
906
+ }
907
+
908
+ void setLastPersistedToEpoch()
909
+ {
910
+ Lock<Mutex> guard(_subLock);
911
+ _setLastPersistedToEpoch();
912
+ }
913
+
914
+ private:
915
+ Subscription(const Subscription&);
916
+ Subscription& operator=(const Subscription&);
917
+
918
+ size_t moveEntry(size_t index_)
919
+ {
920
+ // Check for wrap
921
+ if (_current >= _entriesLength)
922
+ {
923
+ _current = 0;
924
+ _currentBase += _entriesLength;
925
+ }
926
+ // Check for resize
927
+ // If list is too small, double it
928
+ if ((_current == _least % _entriesLength &&
929
+ _leastBase < _currentBase) ||
930
+ (_current == _recoveryMin && _recoveryBase < _currentBase))
931
+ {
932
+ if (!_store->resize(_id, (char**)&_entries,
933
+ sizeof(Entry) * _entriesLength * 2))
934
+ {
935
+ return AMPS_UNSET_INDEX;
936
+ }
937
+ // Length was doubled
938
+ _entriesLength *= 2;
939
+ }
940
+ _entries[_current]._val = _entries[index_]._val;
941
+ _entries[_current]._active = _entries[index_]._active;
942
+ // No need to clear Field, just set it to empty
943
+ _entries[index_]._val.assign(NULL, 0);
944
+ _entries[index_]._active = false;
945
+ return _current++;
946
+ }
947
+
948
+ void _setLastPersistedToEpoch()
949
+ {
950
+ size_t fieldLen = strlen(AMPS_BOOKMARK_EPOCH);
951
+ char* field = new char[fieldLen];
952
+ memcpy(field, AMPS_BOOKMARK_EPOCH, fieldLen);
953
+ _lastPersisted.clear();
954
+ _lastPersisted.assign(field, fieldLen);
955
+ }
956
+
957
+ bool _discard(size_t index_)
958
+ {
959
+ bool retVal = false;
960
+ // Lock should already be held
961
+ assert((_recoveryBase == AMPS_UNSET_INDEX && _recoveryMin == AMPS_UNSET_INDEX) ||
962
+ (_recoveryBase != AMPS_UNSET_INDEX && _recoveryMin != AMPS_UNSET_INDEX));
963
+ size_t base = (_recoveryBase == AMPS_UNSET_INDEX
964
+ || index_ >= _least + _leastBase)
965
+ ? _leastBase : _recoveryBase;
966
+ // discard of a record not in the log is a no-op
967
+ size_t min = (_recoveryMin == AMPS_UNSET_INDEX ? _least + _leastBase :
968
+ _recoveryMin + _recoveryBase);
969
+ if (index_ >= _current + _currentBase || index_ < min)
970
+ {
971
+ return retVal;
972
+ }
973
+
974
+ // log that this one is discarded, then
975
+ // recalculate what the most recent entry is.
976
+ Entry& e = _entries[(index_ - base) % _entriesLength];
977
+ e._active = false;
978
+
979
+ size_t index = index_;
980
+ if (_recoveryMin != AMPS_UNSET_INDEX &&
981
+ index_ == _recoveryMin + _recoveryBase)
982
+ {
983
+ // Find all to discard
984
+ size_t j = _recoveryMin;
985
+ while (j + _recoveryBase < _recoveryMax + _recoveryMaxBase &&
986
+ !_entries[j]._active)
987
+ {
988
+ // This index might be left-over from a slow discard and we
989
+ // may have reconnected. We have a few possibilities at this point.
990
+ // 1. If we re-logged this bookmark, this index will point at an
991
+ // empty bookmark. This could happen if the discard thread was slow
992
+ // and the reconnect was fast. We wouldn't report the
993
+ // the re-arrival of the bookmark as a duplicate because it
994
+ // hadn't been marked as discarded. In this case, we have to
995
+ // simply move past this in the recovery area.
996
+ // 2. This bookmark should become _recent because we haven't
997
+ // yet received anything since our last call to getMostRecent.
998
+ // In this case, we need to take it out of recovered but not
999
+ // clear it. The publishers map should report it as duplicate.
1000
+ // 3. This is the 'oldest' recovered, but we have received new
1001
+ // bookmarks since we got this one. We can clear it because the
1002
+ // publishers map should report it as a duplicate if/when it
1003
+ // does arrive again. Move the _recoveryMin ahead and remove it
1004
+ // from recovered.
1005
+ Message::Field& bookmark = _entries[j]._val;
1006
+ // Option 1 skips this and just moves on
1007
+ if (!bookmark.empty())
1008
+ {
1009
+ _recovered.erase(bookmark);
1010
+ // Make sure our publishers map will mark it discarded
1011
+ amps_uint64_t publisher, sequence;
1012
+ parseBookmark(bookmark, publisher, sequence);
1013
+ PublisherIterator pub = _publishers.find(publisher);
1014
+ if (pub == _publishers.end() || pub->second < sequence)
1015
+ {
1016
+ _publishers[publisher] = sequence;
1017
+ }
1018
+ if (_least + _leastBase == _current + _currentBase ||
1019
+ ((_least + _leastBase) % _entriesLength) ==
1020
+ ((_recoveryMin + _recoveryBase + 1)) % _entriesLength)
1021
+ {
1022
+ // Option 2, reset recent
1023
+ retVal = true;
1024
+ _store->_recentChanged = true;
1025
+ _recoveryTimestamp.clear();
1026
+ _recent.clear();
1027
+ _recent = bookmark;
1028
+ bookmark.assign(NULL, 0);
1029
+ }
1030
+ else
1031
+ {
1032
+ // Option 3, simply clear this one
1033
+ bookmark.clear();
1034
+ }
1035
+ }
1036
+ // If we reach the buffer end,
1037
+ // keep checking from the beginning
1038
+ if (++j == _entriesLength)
1039
+ {
1040
+ // Least has now loooped around
1041
+ _recoveryBase += _entriesLength;
1042
+ j = 0;
1043
+ }
1044
+ }
1045
+ assert(j + _recoveryBase != _recoveryMax + _recoveryMaxBase ||
1046
+ _recovered.empty());
1047
+ if (_recovered.empty())
1048
+ {
1049
+ _recoveryMin = AMPS_UNSET_INDEX;
1050
+ _recoveryBase = AMPS_UNSET_INDEX;
1051
+ _recoveryMax = AMPS_UNSET_INDEX;
1052
+ _recoveryMaxBase = AMPS_UNSET_INDEX;
1053
+ // Cleared recovered, want to check onward
1054
+ index = _least + _leastBase;
1055
+ }
1056
+ else
1057
+ {
1058
+ _recoveryMin = j;
1059
+ }
1060
+ }
1061
+ // if this is the first item in the list, discard all inactive ones
1062
+ // as long as recovery also says its okay
1063
+ if (index == _least + _leastBase)
1064
+ {
1065
+ // Find all to discard
1066
+ size_t j = _least;
1067
+ while (j + _leastBase < _current + _currentBase &&
1068
+ !_entries[j]._active)
1069
+ {
1070
+ //Must free associated memory
1071
+ _recent.clear();
1072
+ _recent = _entries[j]._val;
1073
+ _entries[j]._val.assign(NULL, 0);
1074
+ _store->_recentChanged = true;
1075
+ retVal = true;
1076
+ _recoveryTimestamp.clear();
1077
+ // If we reach the buffer end,
1078
+ // keep checking from the beginning
1079
+ if (++j == _entriesLength)
1080
+ {
1081
+ // Least has now loooped around
1082
+ _leastBase += _entriesLength;
1083
+ j = 0;
1084
+ }
1085
+ }
1086
+ _least = j;
1087
+ }
1088
+ return retVal;
1089
+ }
1090
+
1091
+ void _updateMostRecent()
1092
+ {
1093
+ // Lock is already held
1094
+ _recovered.clear();
1095
+ assert((_recoveryBase == AMPS_UNSET_INDEX && _recoveryMin == AMPS_UNSET_INDEX) ||
1096
+ (_recoveryBase != AMPS_UNSET_INDEX && _recoveryMin != AMPS_UNSET_INDEX));
1097
+ size_t base = (_recoveryMin == AMPS_UNSET_INDEX) ? _leastBase : _recoveryBase;
1098
+ size_t start = (_recoveryMin == AMPS_UNSET_INDEX) ? _least : _recoveryMin;
1099
+ _recoveryMin = AMPS_UNSET_INDEX;
1100
+ _recoveryBase = AMPS_UNSET_INDEX;
1101
+ _recoveryMax = AMPS_UNSET_INDEX;
1102
+ _recoveryMaxBase = AMPS_UNSET_INDEX;
1103
+ for (size_t i = start; i + base < _current + _currentBase; i++)
1104
+ {
1105
+ if ( i >= _entriesLength )
1106
+ {
1107
+ i = 0;
1108
+ base = _currentBase;
1109
+ }
1110
+ if (i >= _recoveryMax + _recoveryBase && i < _least + _leastBase)
1111
+ {
1112
+ continue;
1113
+ }
1114
+ Entry& entry = _entries[i];
1115
+ if (!entry._val.empty())
1116
+ {
1117
+ _recovered[entry._val] = i + base;
1118
+ if (_recoveryMin == AMPS_UNSET_INDEX)
1119
+ {
1120
+ _recoveryMin = i;
1121
+ _recoveryBase = base;
1122
+ _recoveryMax = _current;
1123
+ _recoveryMaxBase = _currentBase;
1124
+ }
1125
+ }
1126
+ }
1127
+ if (_current == _entriesLength)
1128
+ {
1129
+ _current = 0;
1130
+ _currentBase += _entriesLength;
1131
+ }
1132
+ _least = _current;
1133
+ _leastBase = _currentBase;
1134
+ }
1135
+
1136
+ Message::Field _id;
1137
+ Message::Field _recent;
1138
+ Message::Field _lastPersisted;
1139
+ Message::Field _recentList;
1140
+ BookmarkRange _range;
1141
+ Message::Field _recoveryTimestamp;
1142
+ size_t _current;
1143
+ size_t _currentBase;
1144
+ size_t _least;
1145
+ size_t _leastBase;
1146
+ size_t _recoveryMin;
1147
+ size_t _recoveryBase;
1148
+ size_t _recoveryMax;
1149
+ size_t _recoveryMaxBase;
1150
+ size_t _entriesLength;
1151
+ Entry* _entries;
1152
+ MemoryBookmarkStore* _store;
1153
+ Mutex _subLock;
1154
+ RecoveryMap _recovered;
1155
+ public:
1156
+ PublisherMap _publishers;
1157
+ };
1158
+
1159
+ public:
1160
+ ///
1161
+ /// Creates a MemoryBookmarkStore
1162
+ MemoryBookmarkStore() : BookmarkStoreImpl(),
1163
+ _subsLock(),
1164
+ _lock(),
1165
+ _serverVersion(AMPS_DEFAULT_MIN_VERSION),
1166
+ _recentChanged(true),
1167
+ _recovering(false),
1168
+ _recoveryPointAdapter(NULL),
1169
+ _recoveryPointFactory(NULL)
1170
+ { ; }
1171
+
1172
+ typedef RecoveryPointAdapter::iterator RecoveryIterator;
1173
+
1174
+ ///
1175
+ /// Creates a MemoryBookmarkStore
1176
+ /// \param adapter_ The {@link RecoveryPointAdapter} to notify
1177
+ /// about updates.
1178
+ /// \param factory_ An optional factory function to use
1179
+ /// to create the {@link RecoveryPoint} objects sent to the recoveryPointAdapter_.
1180
+ MemoryBookmarkStore(const RecoveryPointAdapter& adapter_,
1181
+ RecoveryPointFactory factory_ = NULL)
1182
+ : BookmarkStoreImpl()
1183
+ , _subsLock()
1184
+ , _lock()
1185
+ , _serverVersion(AMPS_DEFAULT_MIN_VERSION)
1186
+ , _recentChanged(true)
1187
+ , _recovering(true)
1188
+ , _recoveryPointAdapter(adapter_)
1189
+ , _recoveryPointFactory(factory_)
1190
+ {
1191
+ Message msg;
1192
+ for (RecoveryIterator recoveryPoint = _recoveryPointAdapter.begin();
1193
+ recoveryPoint != _recoveryPointAdapter.end();
1194
+ ++recoveryPoint)
1195
+ {
1196
+ Field subId(recoveryPoint->getSubId());
1197
+ msg.setSubscriptionHandle(static_cast<amps_subscription_handle>(0));
1198
+ msg.setSubId(subId);
1199
+ Field bookmark = recoveryPoint->getBookmark();
1200
+ if (BookmarkRange::isRange(bookmark))
1201
+ {
1202
+ msg.setBookmark(bookmark);
1203
+ _log(msg);
1204
+ }
1205
+ else
1206
+ {
1207
+ std::vector<Field> bmList = Field::parseBookmarkList(bookmark);
1208
+ for (std::vector<Field>::iterator bkmk = bmList.begin(); bkmk != bmList.end(); ++bkmk)
1209
+ {
1210
+ if (Field::isTimestamp(*bkmk))
1211
+ {
1212
+ find(subId)->setRecoveryTimestamp(bkmk->data(), bkmk->len());
1213
+ }
1214
+ else
1215
+ {
1216
+ msg.assignBookmark(bkmk->data(), bkmk->len());
1217
+ _isDiscarded(msg);
1218
+ _log(msg);
1219
+ _discard(msg);
1220
+ }
1221
+ }
1222
+ // Reset to original bookmark
1223
+ msg.setBookmark(bookmark);
1224
+ }
1225
+ }
1226
+ _recovering = false;
1227
+ }
1228
+
1229
+ virtual ~MemoryBookmarkStore()
1230
+ {
1231
+ __purge();
1232
+ }
1233
+
1234
+ ///
1235
+ /// Log a bookmark to the persistent log and return the corresponding
1236
+ /// sequence number for this bookmark.
1237
+ /// \param message_ The Message to log.
1238
+ ///
1239
+ virtual size_t log(Message& message_)
1240
+ {
1241
+ Lock<Mutex> guard(_lock);
1242
+ return _log(message_);
1243
+ }
1244
+
1245
+ ///
1246
+ /// Log a discard-bookmark entry to the persistent log
1247
+ /// based on a bookmark sequence number.
1248
+ /// \param message_ The Message to discard.
1249
+ ///
1250
+ virtual void discard(const Message& message_)
1251
+ {
1252
+ Lock<Mutex> guard(_lock);
1253
+ (void)_discard(message_);
1254
+ }
1255
+
1256
+ ///
1257
+ /// Log a discard-bookmark entry to the persistent log
1258
+ /// based on a bookmark sequence number. Use the \ref discard(const Message&)
1259
+ /// function instead when you have the full Message object available..
1260
+ /// \param subId_ The id of the subscription to which the bookmark applies.
1261
+ /// \param bookmarkSeqNo_ The bookmark sequence number to discard.
1262
+ ///
1263
+ virtual void discard(const Message::Field& subId_, size_t bookmarkSeqNo_)
1264
+ {
1265
+ Lock<Mutex> guard(_lock);
1266
+ (void)_discard(subId_, bookmarkSeqNo_);
1267
+ }
1268
+
1269
+ ///
1270
+ /// Returns the most recent bookmark from the log that
1271
+ /// ought to be used for (re-)subscriptions.
1272
+ /// \param subId_ The id of the subscription to check.
1273
+ ///
1274
+ virtual Message::Field getMostRecent(const Message::Field& subId_)
1275
+ {
1276
+ Lock<Mutex> guard(_lock);
1277
+ return _getMostRecent(subId_);
1278
+ }
1279
+
1280
+ ///
1281
+ /// Called for each arriving message to determine if
1282
+ /// the application has already seen this bookmark and should
1283
+ /// not be reprocessed. Returns 'true' if the bookmark is
1284
+ /// in the log and should not be re-processed, false otherwise.
1285
+ /// \param message_ The Message to check.
1286
+ /// \return Whether or not the Message has been discarded from this store.
1287
+ ///
1288
+ virtual bool isDiscarded(Message& message_)
1289
+ {
1290
+ Lock<Mutex> guard(_lock);
1291
+ return _isDiscarded(message_);
1292
+ }
1293
+
1294
+ ///
1295
+ /// Called to purge the contents of this store.
1296
+ /// Removes any tracking history associated with publishers and received
1297
+ /// messages, and may delete or truncate on-disk representations as well.
1298
+ ///
1299
+ virtual void purge()
1300
+ {
1301
+ Lock<Mutex> guard(_lock);
1302
+ _purge();
1303
+ }
1304
+
1305
+ ///
1306
+ /// Called to purge the contents of this store for particular subId.
1307
+ /// Removes any tracking history associated with publishers and received
1308
+ /// messages, and will remove the subId from the file as well.
1309
+ ///
1310
+ virtual void purge(const Message::Field& subId_)
1311
+ {
1312
+ Lock<Mutex> guard(_lock);
1313
+ _purge(subId_);
1314
+ }
1315
+
1316
+ ///
1317
+ /// Called to find the oldest bookmark in the store.
1318
+ /// \param subId_ The subscription ID on which to find the oldest bookmark.
1319
+ /// \return The bookmark that is oldest in the store for subId_
1320
+ virtual size_t getOldestBookmarkSeq(const Message::Field& subId_)
1321
+ {
1322
+ Lock<Mutex> guard(_lock);
1323
+ return _getOldestBookmarkSeq(subId_);
1324
+ }
1325
+
1326
+ ///
1327
+ /// Mark the bookmark provided as replicated to all sync replication
1328
+ /// destinations for the given subscription.
1329
+ /// \param subId_ The subscription Id to which the bookmark applies.
1330
+ /// \param bookmark_ The most recent replicated bookmark.
1331
+ virtual void persisted(const Message::Field& subId_,
1332
+ const Message::Field& bookmark_)
1333
+ {
1334
+ Lock<Mutex> guard(_lock);
1335
+ _persisted(find(subId_), bookmark_);
1336
+ }
1337
+
1338
+ ///
1339
+ /// Mark the bookmark provided as replicated to all sync replication
1340
+ /// destinations for the given subscription.
1341
+ /// \param subId_ The subscription Id to which the bookmark applies.
1342
+ /// \param bookmark_ The most recent bookmark's sequence number.
1343
+ /// \return The bookmark field that was just marked persisted.
1344
+ virtual Message::Field persisted(const Message::Field& subId_,
1345
+ size_t bookmark_)
1346
+ {
1347
+ Lock<Mutex> guard(_lock);
1348
+ return _persisted(find(subId_), bookmark_);
1349
+ }
1350
+
1351
+ ///
1352
+ /// Internally used to set the server version so the store knows how to deal
1353
+ /// with persisted acks and calls to getMostRecent().
1354
+ /// \param version_ The version of the server being used.
1355
+ void setServerVersion(const VersionInfo& version_)
1356
+ {
1357
+ setServerVersion(version_.getOldStyleVersion());
1358
+ }
1359
+
1360
+ ///
1361
+ /// Internally used to set the server version so the store knows how to deal
1362
+ /// with persisted acks and calls to getMostRecent().
1363
+ /// \param version_ The version of the server being used.
1364
+ void setServerVersion(size_t version_)
1365
+ {
1366
+ Lock<Mutex> guard(_subsLock);
1367
+ _serverVersion = version_;
1368
+ }
1369
+
1370
+ inline bool isWritableBookmark(size_t length)
1371
+ {
1372
+ return length >= AMPS_MIN_BOOKMARK_LEN;
1373
+ }
1374
+
1375
+ typedef Subscription::EntryPtrList EntryPtrList;
1376
+
1377
+ protected:
1378
+
1379
+ // Called once lock is acquired
1380
+ size_t _log(Message& message_)
1381
+ {
1382
+ Message::Field bookmark = message_.getBookmark();
1383
+ Subscription* pSub = (Subscription*)(message_.getSubscriptionHandle());
1384
+ if (!pSub)
1385
+ {
1386
+ Message::Field subId = message_.getSubscriptionId();
1387
+ if (subId.empty())
1388
+ {
1389
+ subId = message_.getSubscriptionIds();
1390
+ }
1391
+ pSub = find(subId);
1392
+ message_.setSubscriptionHandle(
1393
+ static_cast<amps_subscription_handle>(pSub));
1394
+ }
1395
+ size_t retVal = pSub->log(bookmark);
1396
+ message_.setBookmarkSeqNo(retVal);
1397
+ return retVal;
1398
+ }
1399
+
1400
+ // Called once lock is acquired
1401
+ bool _discard(const Message& message_)
1402
+ {
1403
+ size_t bookmarkSeqNo = message_.getBookmarkSeqNo();
1404
+ Subscription* pSub = (Subscription*)(message_.getSubscriptionHandle());
1405
+ if (!pSub)
1406
+ {
1407
+ Message::Field subId = message_.getSubscriptionId();
1408
+ if (subId.empty())
1409
+ {
1410
+ subId = message_.getSubscriptionIds();
1411
+ }
1412
+ pSub = find(subId);
1413
+ }
1414
+ bool retVal = pSub->discard(bookmarkSeqNo);
1415
+ if (retVal)
1416
+ {
1417
+ updateAdapter(pSub);
1418
+ }
1419
+ return retVal;
1420
+ }
1421
+
1422
+ // Called once lock is acquired
1423
+ bool _discard(const Message::Field& subId_, size_t bookmarkSeqNo_)
1424
+ {
1425
+ Subscription* pSub = find(subId_);
1426
+ bool retVal = pSub->discard(bookmarkSeqNo_);
1427
+ if (retVal)
1428
+ {
1429
+ updateAdapter(pSub);
1430
+ }
1431
+ return retVal;
1432
+ }
1433
+
1434
+ // Called once lock is acquired
1435
+ Message::Field _getMostRecent(const Message::Field& subId_,
1436
+ bool usePublishersList_ = true)
1437
+ {
1438
+ Subscription* pSub = find(subId_);
1439
+ return pSub->getMostRecentList(usePublishersList_);
1440
+ }
1441
+
1442
+ // Called once lock is acquired
1443
+ bool _isDiscarded(Message& message_)
1444
+ {
1445
+ Message::Field subId = message_.getSubscriptionId();
1446
+ if (subId.empty())
1447
+ {
1448
+ subId = message_.getSubscriptionIds();
1449
+ }
1450
+ Subscription* pSub = find(subId);
1451
+ message_.setSubscriptionHandle(
1452
+ static_cast<amps_subscription_handle>(pSub));
1453
+ return pSub->isDiscarded(message_.getBookmark());
1454
+ }
1455
+
1456
+ // Called once lock is acquired
1457
+ size_t _getOldestBookmarkSeq(const Message::Field& subId_)
1458
+ {
1459
+ Subscription* pSub = find(subId_);
1460
+ return pSub->getOldestBookmarkSeq();
1461
+ }
1462
+
1463
+ // Called once lock is acquired
1464
+ virtual void _persisted(Subscription* pSub_,
1465
+ const Message::Field& bookmark_)
1466
+ {
1467
+ if (pSub_->lastPersisted(bookmark_))
1468
+ {
1469
+ updateAdapter(pSub_);
1470
+ }
1471
+ }
1472
+
1473
+ // Called once lock is acquired
1474
+ virtual Message::Field _persisted(Subscription* pSub_, size_t bookmark_)
1475
+ {
1476
+ return pSub_->lastPersisted(bookmark_);
1477
+ }
1478
+
1479
+ // Called once lock is acquired
1480
+ void _purge()
1481
+ {
1482
+ if (_recoveryPointAdapter.isValid())
1483
+ {
1484
+ _recoveryPointAdapter.purge();
1485
+ }
1486
+ __purge();
1487
+ }
1488
+
1489
+ // Called once lock is acquired
1490
+ void __purge()
1491
+ {
1492
+ // Walk through list and clear Fields before calling clear
1493
+ while (!_subs.empty())
1494
+ {
1495
+ SubscriptionMap::iterator iter = _subs.begin();
1496
+ //The subId key is cleared when deleting the Subscription, which shares
1497
+ //the _data pointer in its id field.
1498
+ const_cast<Message::Field&>(iter->first).clear();
1499
+ delete (iter->second);
1500
+ _subs.erase(iter);
1501
+ }
1502
+ _subs.clear();
1503
+ }
1504
+
1505
+ // Called once lock is acquired
1506
+ virtual void _purge(const Message::Field& subId_)
1507
+ {
1508
+ if (_recoveryPointAdapter.isValid())
1509
+ {
1510
+ _recoveryPointAdapter.purge(subId_);
1511
+ }
1512
+ __purge(subId_);
1513
+ }
1514
+
1515
+ // Called once lock is acquired
1516
+ virtual void __purge(const Message::Field& subId_)
1517
+ {
1518
+ Lock<Mutex> guard(_subsLock);
1519
+ SubscriptionMap::iterator iter = _subs.find(subId_);
1520
+ if (iter == _subs.end())
1521
+ {
1522
+ return;
1523
+ }
1524
+ const_cast<Message::Field&>(iter->first).clear();
1525
+ delete (iter->second);
1526
+ _subs.erase(iter);
1527
+ }
1528
+
1529
+ // Can be used by subclasses during recovery
1530
+ void setMostRecent(const Message::Field& subId_,
1531
+ const Message::Field& recent_)
1532
+ {
1533
+ find(subId_)->setMostRecent(recent_);
1534
+ }
1535
+
1536
+ Mutex _subsLock;
1537
+ Mutex _lock;
1538
+ static const char ENTRY_BOOKMARK = 'b';
1539
+ static const char ENTRY_DISCARD = 'd';
1540
+ static const char ENTRY_PERSISTED = 'p';
1541
+
1542
+ virtual Subscription* find(const Message::Field& subId_)
1543
+ {
1544
+ if (subId_.empty())
1545
+ {
1546
+ throw StoreException("A valid subscription ID must be provided to the Bookmark Store");
1547
+ }
1548
+ Lock<Mutex> guard(_subsLock);
1549
+ if (_subs.count(subId_) == 0)
1550
+ {
1551
+ // Subscription will be created
1552
+ Message::Field id;
1553
+ id.deepCopy(subId_);
1554
+ _subs[id] = new Subscription(this, id);
1555
+ return _subs[id];
1556
+ }
1557
+ return _subs[subId_];
1558
+ }
1559
+
1560
+ virtual bool resize(const Message::Field& subId_, char** newBuffer_, size_t size_,
1561
+ bool callResizeHandler_ = true)
1562
+ {
1563
+ assert(newBuffer_ != 0);
1564
+ if (size_ == 0) // Delete the buffer
1565
+ {
1566
+ if (*newBuffer_)
1567
+ {
1568
+ free(*newBuffer_);
1569
+ *newBuffer_ = NULL;
1570
+ }
1571
+ return true;
1572
+ }
1573
+ if (callResizeHandler_ && !callResizeHandler(subId_, size_))
1574
+ {
1575
+ return false;
1576
+ }
1577
+ char* oldBuffer = *newBuffer_ ? *newBuffer_ : NULL;
1578
+ *newBuffer_ = (char*)malloc(size_);
1579
+ memset(*newBuffer_, 0, size_);
1580
+ if (oldBuffer)
1581
+ {
1582
+ find(subId_)->moveEntries(oldBuffer, *newBuffer_, size_);
1583
+ free(oldBuffer);
1584
+ }
1585
+ return true;
1586
+ }
1587
+
1588
+ protected:
1589
+ void updateAdapter(Subscription* pSub_)
1590
+ {
1591
+ if (_recovering || !_recentChanged || !_recoveryPointAdapter.isValid())
1592
+ {
1593
+ return;
1594
+ }
1595
+ if (_recoveryPointFactory)
1596
+ {
1597
+ RecoveryPoint update(_recoveryPointFactory(pSub_->id(),
1598
+ pSub_->getMostRecentList(false)));
1599
+ _recoveryPointAdapter.update(update);
1600
+ }
1601
+ else
1602
+ {
1603
+ RecoveryPoint update(new FixedRecoveryPoint(pSub_->id(),
1604
+ pSub_->getMostRecentList(false)));
1605
+ _recoveryPointAdapter.update(update);
1606
+ }
1607
+ }
1608
+
1609
+ typedef std::map<Message::Field, Subscription*, Message::Field::FieldHash> SubscriptionMap;
1610
+ SubscriptionMap _subs;
1611
+ size_t _serverVersion;
1612
+ bool _recentChanged;
1613
+ bool _recovering;
1614
+ typedef std::set<Subscription*> SubscriptionSet;
1615
+ RecoveryPointAdapter _recoveryPointAdapter;
1616
+ RecoveryPointFactory _recoveryPointFactory;
1617
+ };
1618
+
1619
+ } // end namespace AMPS
1620
+
1621
+ #endif //_MEMORYBOOKMARKSTORE_H_
1622
+