shareddata 6.85.1__tar.gz → 6.85.3__tar.gz

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 (187) hide show
  1. {shareddata-6.85.1/src/shareddata.egg-info → shareddata-6.85.3}/PKG-INFO +1 -1
  2. {shareddata-6.85.1 → shareddata-6.85.3}/setup.py +1 -1
  3. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Table.py +21 -0
  4. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/TableDisk.py +116 -17
  5. {shareddata-6.85.1 → shareddata-6.85.3/src/shareddata.egg-info}/PKG-INFO +1 -1
  6. {shareddata-6.85.1 → shareddata-6.85.3}/LICENSE +0 -0
  7. {shareddata-6.85.1 → shareddata-6.85.3}/MANIFEST.in +0 -0
  8. {shareddata-6.85.1 → shareddata-6.85.3}/README.md +0 -0
  9. {shareddata-6.85.1 → shareddata-6.85.3}/pyproject.toml +0 -0
  10. {shareddata-6.85.1 → shareddata-6.85.3}/setup.cfg +0 -0
  11. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/ServerGunicorn.py +0 -0
  12. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/ServerWaitress.py +0 -0
  13. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/__init__.py +0 -0
  14. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/apidocs-dark.css +0 -0
  15. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/apidocs.yml +0 -0
  16. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/auth.py +0 -0
  17. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/constants.py +0 -0
  18. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/download_paths.py +0 -0
  19. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/download_slots.py +0 -0
  20. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/install/worker.ps1 +0 -0
  21. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/install/worker.sh +0 -0
  22. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/listcache.py +0 -0
  23. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/routes/__init__.py +0 -0
  24. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/routes/cache.py +0 -0
  25. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/routes/collections.py +0 -0
  26. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/routes/data.py +0 -0
  27. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/routes/downloads.py +0 -0
  28. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/routes/metadata.py +0 -0
  29. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/routes/operations.py +0 -0
  30. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/routes/schedules.py +0 -0
  31. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/routes/sqlite.py +0 -0
  32. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/routes/system.py +0 -0
  33. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/routes/tables.py +0 -0
  34. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/routes/timeseries.py +0 -0
  35. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/routes/web_routes.py +0 -0
  36. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/routes/workers.py +0 -0
  37. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/API/utils.py +0 -0
  38. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Auth/__init__.py +0 -0
  39. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Auth/bootstrap.py +0 -0
  40. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Auth/migrate.py +0 -0
  41. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Auth/store.py +0 -0
  42. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Auth/workers.py +0 -0
  43. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/CacheRedis.py +0 -0
  44. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/CollectionMongoDB.py +0 -0
  45. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/DataAPI/__init__.py +0 -0
  46. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/DataAPI/catalog.py +0 -0
  47. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/DataAPI/config.py +0 -0
  48. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/DataAPI/errors.py +0 -0
  49. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/DataAPI/indexes.py +0 -0
  50. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/DataAPI/readers.py +0 -0
  51. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/DataAPI/resolve.py +0 -0
  52. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/DataAPI/service.py +0 -0
  53. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Database.py +0 -0
  54. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Defaults.py +0 -0
  55. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/IO/AWSEC2.py +0 -0
  56. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/IO/AWSS3.py +0 -0
  57. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/IO/AutoDocstrings.py +0 -0
  58. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/IO/ClientAPI.py +0 -0
  59. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/IO/ClientSocket.py +0 -0
  60. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/IO/ClientWebSocket.py +0 -0
  61. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/IO/LogHandlerAPI.py +0 -0
  62. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/IO/LogReader.py +0 -0
  63. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/IO/MongoDBClient.py +0 -0
  64. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/IO/SaveTables.py +0 -0
  65. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/IO/ServerSocket.py +0 -0
  66. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/IO/ServerWebSocket.py +0 -0
  67. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/IO/StreamsCache.py +0 -0
  68. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/IO/StreamsPersist.py +0 -0
  69. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/IO/SyncTable.py +0 -0
  70. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/IO/TunnelWebSocket.py +0 -0
  71. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/IO/__init__.py +0 -0
  72. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Listing.py +0 -0
  73. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/LockWaiters.py +0 -0
  74. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Logger.py +0 -0
  75. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/MCP/__init__.py +0 -0
  76. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/MCP/__main__.py +0 -0
  77. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/MCP/client.py +0 -0
  78. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/MCP/server.py +0 -0
  79. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Metadata.py +0 -0
  80. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/MultiProc.py +0 -0
  81. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/OpenFIGI.py +0 -0
  82. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Redaction.py +0 -0
  83. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Routines/ArchiveOldCollections.py +0 -0
  84. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Routines/BatchJob.py +0 -0
  85. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Routines/ContainerHealth.py +0 -0
  86. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Routines/JobStore.py +0 -0
  87. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Routines/RoutineCommand.py +0 -0
  88. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Routines/RoutineOrigin.py +0 -0
  89. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Routines/Schedule.py +0 -0
  90. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Routines/ScheduleMirror.py +0 -0
  91. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Routines/ScheduleMonitor.py +0 -0
  92. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Routines/ScheduleStore.py +0 -0
  93. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Routines/Scheduler.py +0 -0
  94. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Routines/UpdateActiveJobs.py +0 -0
  95. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Routines/Worker.py +0 -0
  96. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Routines/WorkerBootstrap.py +0 -0
  97. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Routines/WorkerLib.py +0 -0
  98. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Routines/WorkerPool.py +0 -0
  99. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Routines/__init__.py +0 -0
  100. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/SQLite.py +0 -0
  101. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/SharedData.py +0 -0
  102. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/SharedNumpy.py +0 -0
  103. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/StreamKafka.py +0 -0
  104. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Symbol.py +0 -0
  105. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/TableIndex.py +0 -0
  106. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/TableIndexJitFunctions.py +0 -0
  107. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/TableIndexJitFunctionsManual.py +0 -0
  108. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/TableIndexJitGenerate.py +0 -0
  109. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/TableIndexJitHash.py +0 -0
  110. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/TableIndexJitLoc.py +0 -0
  111. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/TableProtocol.py +0 -0
  112. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/TableRead.py +0 -0
  113. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/TableRewrite.py +0 -0
  114. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/TimeSeriesDisk.py +0 -0
  115. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/TimeseriesContainer.py +0 -0
  116. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Users.py +0 -0
  117. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Utils.py +0 -0
  118. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/ADDING_A_PAGE.md +0 -0
  119. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/__init__.py +0 -0
  120. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/activity_logger.py +0 -0
  121. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/app.py +0 -0
  122. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/assets/dashAgGridComponentFunctions.js +0 -0
  123. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/assets/dashAgGridFunctions.js +0 -0
  124. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/assets/google_logo.png +0 -0
  125. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/assets/kafka_keys.js +0 -0
  126. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/assets/logs.css +0 -0
  127. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/assets/sched.css +0 -0
  128. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/assets/styles.css +0 -0
  129. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/auth.py +0 -0
  130. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/backends.py +0 -0
  131. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/config.py +0 -0
  132. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/containers.py +0 -0
  133. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/identity.py +0 -0
  134. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/kafka_view.py +0 -0
  135. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/mongo_view.py +0 -0
  136. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/proc.py +0 -0
  137. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/redis_view.py +0 -0
  138. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/route_health.py +0 -0
  139. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/route_registry.py +0 -0
  140. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/sched.py +0 -0
  141. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/schedule_editor.py +0 -0
  142. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/server.py +0 -0
  143. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/services.py +0 -0
  144. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/shell.py +0 -0
  145. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/standalone.py +0 -0
  146. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/static/account.js +0 -0
  147. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/static/custom.css +0 -0
  148. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/static/favicon.ico +0 -0
  149. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/static/favicon.png +0 -0
  150. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/static/logo.png +0 -0
  151. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/static/logo_96x96.png +0 -0
  152. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/static/shareddata-mark.svg +0 -0
  153. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/static/shell.css +0 -0
  154. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/static/shell.js +0 -0
  155. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/static/standalone.css +0 -0
  156. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/static/standalone.js +0 -0
  157. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/suggest.py +0 -0
  158. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/templates/account.html +0 -0
  159. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/templates/base.html +0 -0
  160. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/templates/claim.html +0 -0
  161. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/templates/claim_done.html +0 -0
  162. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/templates/dash.html +0 -0
  163. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/templates/index.html +0 -0
  164. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/templates/login.html +0 -0
  165. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/templates/login_2fa.html +0 -0
  166. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/templates/partials/navbar.html +0 -0
  167. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/templates/partials/scripts.html +0 -0
  168. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/templates/recovery_codes.html +0 -0
  169. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/templates/shell.html +0 -0
  170. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/templates/standalone.html +0 -0
  171. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/twofactor.py +0 -0
  172. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/utils.py +0 -0
  173. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/Web/workerpool.py +0 -0
  174. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/__init__.py +0 -0
  175. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/build_info.py +0 -0
  176. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/fleet.py +0 -0
  177. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/preflight.py +0 -0
  178. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/private_files.py +0 -0
  179. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/release_backup.py +0 -0
  180. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/server.py +0 -0
  181. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/services.py +0 -0
  182. {shareddata-6.85.1 → shareddata-6.85.3}/src/SharedData/sharedmutexwin.pyd +0 -0
  183. {shareddata-6.85.1 → shareddata-6.85.3}/src/shareddata.egg-info/SOURCES.txt +0 -0
  184. {shareddata-6.85.1 → shareddata-6.85.3}/src/shareddata.egg-info/dependency_links.txt +0 -0
  185. {shareddata-6.85.1 → shareddata-6.85.3}/src/shareddata.egg-info/entry_points.txt +0 -0
  186. {shareddata-6.85.1 → shareddata-6.85.3}/src/shareddata.egg-info/requires.txt +0 -0
  187. {shareddata-6.85.1 → shareddata-6.85.3}/src/shareddata.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: shareddata
3
- Version: 6.85.1
3
+ Version: 6.85.3
4
4
  Summary: Memory Mapped / Shared Memory Database with S3 repository
5
5
  Home-page: https://shareddata.net
6
6
  Author: shareddata
@@ -66,7 +66,7 @@ test_requires = [
66
66
 
67
67
  setup(
68
68
  name='shareddata',
69
- version='6.85.1',
69
+ version='6.85.3',
70
70
  description='Memory Mapped / Shared Memory Database with S3 repository',
71
71
  author='shareddata',
72
72
  author_email='admin@shareddata.net',
@@ -865,6 +865,27 @@ class Table:
865
865
  raise RewriteError('automatic disk header migration requires staged publication')
866
866
 
867
867
  ############### DOWNLOAD ###############
868
+ def _remote_change(self):
869
+ """What a reload would have to fetch: 'head' when the remote head is newer than this table's
870
+ (the whole image changed), 'tail' when only the remote tail is (the usual case: the rows of
871
+ the current year), None when nothing is newer, there is no remote copy, or S3 is off."""
872
+ from SharedData.services import s3_enabled
873
+ if not s3_enabled() or self.hdr is None:
874
+ return None
875
+ head = S3GetMtime(str(self.headpath) + '.gzip', self.database_folder)
876
+ if head is not None and head > float(self.hdr['mtimehead']):
877
+ return 'head'
878
+ if int(self.hdr['hastail']) == 1:
879
+ tail = S3GetMtime(str(self.tailpath) + '.gzip', self.database_folder)
880
+ if tail is not None and tail > float(self.hdr['mtimetail']):
881
+ return 'tail'
882
+ return None
883
+
884
+ def _download_remote_tail(self):
885
+ """[io, local mtime, remote mtime] of the remote tail; io is None unless it is newer than this table's."""
886
+ return S3Download(str(self.tailpath) + '.gzip', local_mtime=float(self.hdr['mtimetail']),
887
+ database_folder=self.database_folder)
888
+
868
889
  @structural
869
890
  def download(self):
870
891
  """
@@ -263,27 +263,126 @@ class TableDisk(Table):
263
263
  @structural
264
264
  def reload(self):
265
265
  """
266
- Reloads the table data from disk by performing a sequence of operations to ensure data consistency and resource management.
267
-
268
- The method:
269
- - Acquires necessary locks or resources to safely perform the reload.
270
- - Frees current resources without acquiring new ones to prepare for fresh data.
271
- - Downloads the latest table data from disk.
272
- - Allocates memory for the newly downloaded data.
273
- - If an index exists, resets its creation flag and initializes the index.
274
- - Updates shareddata references to point to the reloaded table.
275
- - Marks the table as loaded in both header and mutex states.
276
- - Handles and logs any exceptions that occur during the reload process.
277
- - Ensures that all acquired resources are released after the operation, regardless of success or failure.
278
-
266
+ Replace the local image with the remote copy when that is newer.
267
+
268
+ Nothing newer remotely (or no remote copy, or S3 off) leaves the local table as it is, so
269
+ rows not uploaded yet are never discarded. When only the remote tail is newer (the usual
270
+ case: the head holds the years before this one and the tail this year's rows) only the tail
271
+ is fetched and applied, see _reload_tail. When the remote head is newer, the whole remote
272
+ image is built beside data.bin under a stage name and installed by one os.replace, inside
273
+ the caller's STRUCT section: a failure before the replace leaves the old image untouched, and the epoch
274
+ published on leaving the section makes other processes reopen the new file. The old index
275
+ files describe the old rows, so they are removed and rebuilt.
276
+
279
277
  Returns:
280
278
  The records of the reloaded table.
281
279
  """
282
- from SharedData.TableRewrite import RewriteError
283
- raise RewriteError('disk reload requires staged remote replacement')
280
+ import stat
281
+ import uuid
282
+ from SharedData.TableRewrite import fsync_directory, read_layout, require_rewrite_support, sync_file
283
+ change = self._remote_change()
284
+ if change is None:
285
+ return self.records
286
+ if change == 'tail' and not self.is_schemaless:
287
+ return self._reload_tail()
288
+ require_rewrite_support()
289
+ final = self.filepath
290
+ old = os.stat(final)
291
+ for leftover in final.parent.glob('data.bin.reload.*'): # the writer lock is held: a stage left by a dead reload
292
+ leftover.unlink()
293
+ stage = final.parent / ('data.bin.reload.' + uuid.uuid4().hex)
294
+ saved = (self.hdr, self.size, getattr(self, 'orig_hdr', None))
295
+ self.filepath, self.hdr = stage, None # None: download the remote image, not what is newer than the local one
296
+ self._bootstrap_record_download = True
297
+ try:
298
+ self._download_empty_image()
299
+ if self.hdr is None or not stage.is_file():
300
+ raise Exception('the remote copy of %s disappeared during the reload' % self.relpath)
301
+ sync_file(stage)
302
+ with open(stage, 'rb') as stream:
303
+ downloaded, _ = read_layout(stream)
304
+ os.chmod(stage, stat.S_IMODE(old.st_mode))
305
+ try:
306
+ os.chown(stage, old.st_uid, old.st_gid)
307
+ except OSError:
308
+ pass
309
+ os.replace(stage, final)
310
+ except BaseException:
311
+ self.filepath = final
312
+ self.hdr, self.size, self.orig_hdr = saved
313
+ try:
314
+ stage.unlink()
315
+ except FileNotFoundError:
316
+ pass
317
+ raise
318
+ finally:
319
+ self._bootstrap_record_download = False
320
+ self.filepath = final
321
+ fsync_directory(final.parent)
322
+ try:
323
+ self.free(acquire=False) # the old mappings and index arrays, flushed first
324
+ for name in ('dateidx.bin', 'pkey.bin', 'symbolidx.bin', 'portidx.bin'):
325
+ try:
326
+ (final.parent / name).unlink()
327
+ except FileNotFoundError:
328
+ pass
329
+ self.malloc()
330
+ if self.hasindex:
331
+ self.hdr['isidxcreated'] = 0
332
+ self.index.initialize()
333
+ self.shareddata.data[self.relpath] = self
334
+ self.hdr['isloaded'] = 1
335
+ self.mutex['isloaded'] = 1
336
+ except Exception as e:
337
+ errmsg = f"TableDisk.reload() {self.relpath}: {e}"
338
+ Logger.log.error(errmsg)
339
+ raise Exception(errmsg)
340
+ return self.records
341
+
342
+ def _reload_tail(self):
343
+ """
344
+ Apply the remote tail alone: its cost is the tail, not the table (that is what the head/tail
345
+ split is for). Runs inside reload's STRUCT section, with the writer lock held.
346
+
347
+ The tail rows are written into the live file right after the head, the file is synced, and
348
+ the header (count, tail size and time) is committed last. A process that dies before the
349
+ commit leaves the old header: the old tail time is still older than the remote one, so the
350
+ next reload applies the tail again, and the index is rebuilt from the committed rows (the
351
+ dead holder leaves the table flagged DIRTY). No reader looks at the file meanwhile: STRUCT
352
+ keeps lock-free readers waiting and the other readers take the same lock.
353
+ """
354
+ from SharedData.TableRewrite import sync_file
355
+ tail_gz, _, remote_mtime = self._download_remote_tail()
356
+ if tail_gz is None: # nothing newer after all
357
+ return self.records
358
+ live, size = self.hdr, self.size
359
+ self.hdr = live.copy() # the mapped header stays as it was until the commit
360
+ self._bootstrap_record_download = True # reload holds the lock: the tail may be written into the live file
361
+ try:
362
+ tail_gz.seek(0) # S3Download leaves the buffer at its end
363
+ tail_io = gzip.GzipFile(fileobj=tail_gz, mode='rb')
364
+ self.read_tailheader(tail_io) # count, tail size and tail time of the new header
365
+ self.hdr['mtimetail'] = remote_mtime
366
+ if int(self.hdr['count']) > int(self.hdr['recordssize']):
367
+ self.hdr['recordssize'] = self.hdr['count']
368
+ if self.size is None or self.size < int(self.hdr['recordssize']):
369
+ self.size = int(self.hdr['recordssize'])
370
+ self.create_file() # a table that grew gets a longer file: never shortened or rewritten
371
+ self.read_tail(tail_io)
372
+ sync_file(self.filepath)
373
+ self.hdr['isloaded'] = 0
374
+ self.hdr['isidxcreated'] = 0
375
+ committed = self.hdr
376
+ except BaseException:
377
+ self.hdr, self.size = live, size
378
+ raise
379
+ finally:
380
+ self._bootstrap_record_download = False
381
+ self.shf_hdr[0] = committed # the commit
382
+ self.shf_hdr.flush()
383
+ sync_file(self.filepath)
284
384
  try:
285
385
  self.free(acquire=False)
286
- self.download()
287
386
  self.malloc()
288
387
  if self.hasindex:
289
388
  self.hdr['isidxcreated'] = 0
@@ -296,7 +395,7 @@ class TableDisk(Table):
296
395
  Logger.log.error(errmsg)
297
396
  raise Exception(errmsg)
298
397
  return self.records
299
-
398
+
300
399
  ############### DELETE ###############
301
400
  def delete_local(self):
302
401
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: shareddata
3
- Version: 6.85.1
3
+ Version: 6.85.3
4
4
  Summary: Memory Mapped / Shared Memory Database with S3 repository
5
5
  Home-page: https://shareddata.net
6
6
  Author: shareddata
File without changes
File without changes
File without changes
File without changes
File without changes