shareddata 6.85.9__tar.gz → 6.85.11__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.9/src/shareddata.egg-info → shareddata-6.85.11}/PKG-INFO +1 -1
  2. {shareddata-6.85.9 → shareddata-6.85.11}/setup.py +1 -1
  3. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/CollectionMongoDB.py +1 -1
  4. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Table.py +30 -4
  5. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/TableDisk.py +6 -1
  6. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/TableProtocol.py +9 -3
  7. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/TableRewrite.py +80 -7
  8. {shareddata-6.85.9 → shareddata-6.85.11/src/shareddata.egg-info}/PKG-INFO +1 -1
  9. {shareddata-6.85.9 → shareddata-6.85.11}/LICENSE +0 -0
  10. {shareddata-6.85.9 → shareddata-6.85.11}/MANIFEST.in +0 -0
  11. {shareddata-6.85.9 → shareddata-6.85.11}/README.md +0 -0
  12. {shareddata-6.85.9 → shareddata-6.85.11}/pyproject.toml +0 -0
  13. {shareddata-6.85.9 → shareddata-6.85.11}/setup.cfg +0 -0
  14. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/ServerGunicorn.py +0 -0
  15. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/ServerWaitress.py +0 -0
  16. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/__init__.py +0 -0
  17. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/apidocs-dark.css +0 -0
  18. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/apidocs.yml +0 -0
  19. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/auth.py +0 -0
  20. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/constants.py +0 -0
  21. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/download_paths.py +0 -0
  22. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/download_slots.py +0 -0
  23. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/install/worker.ps1 +0 -0
  24. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/install/worker.sh +0 -0
  25. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/listcache.py +0 -0
  26. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/routes/__init__.py +0 -0
  27. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/routes/cache.py +0 -0
  28. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/routes/collections.py +0 -0
  29. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/routes/data.py +0 -0
  30. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/routes/downloads.py +0 -0
  31. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/routes/metadata.py +0 -0
  32. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/routes/operations.py +0 -0
  33. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/routes/schedules.py +0 -0
  34. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/routes/sqlite.py +0 -0
  35. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/routes/system.py +0 -0
  36. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/routes/tables.py +0 -0
  37. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/routes/timeseries.py +0 -0
  38. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/routes/web_routes.py +0 -0
  39. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/routes/workers.py +0 -0
  40. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/API/utils.py +0 -0
  41. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Auth/__init__.py +0 -0
  42. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Auth/bootstrap.py +0 -0
  43. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Auth/migrate.py +0 -0
  44. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Auth/store.py +0 -0
  45. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Auth/workers.py +0 -0
  46. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/CacheRedis.py +0 -0
  47. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/DataAPI/__init__.py +0 -0
  48. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/DataAPI/catalog.py +0 -0
  49. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/DataAPI/config.py +0 -0
  50. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/DataAPI/errors.py +0 -0
  51. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/DataAPI/indexes.py +0 -0
  52. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/DataAPI/readers.py +0 -0
  53. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/DataAPI/resolve.py +0 -0
  54. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/DataAPI/service.py +0 -0
  55. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Database.py +0 -0
  56. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Defaults.py +0 -0
  57. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/IO/AWSEC2.py +0 -0
  58. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/IO/AWSS3.py +0 -0
  59. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/IO/AutoDocstrings.py +0 -0
  60. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/IO/ClientAPI.py +0 -0
  61. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/IO/ClientSocket.py +0 -0
  62. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/IO/ClientWebSocket.py +0 -0
  63. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/IO/LogHandlerAPI.py +0 -0
  64. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/IO/LogReader.py +0 -0
  65. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/IO/MongoDBClient.py +0 -0
  66. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/IO/SaveTables.py +0 -0
  67. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/IO/ServerSocket.py +0 -0
  68. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/IO/ServerWebSocket.py +0 -0
  69. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/IO/StreamsCache.py +0 -0
  70. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/IO/StreamsPersist.py +0 -0
  71. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/IO/SyncTable.py +0 -0
  72. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/IO/TunnelWebSocket.py +0 -0
  73. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/IO/__init__.py +0 -0
  74. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Listing.py +0 -0
  75. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/LockWaiters.py +0 -0
  76. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Logger.py +0 -0
  77. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/MCP/__init__.py +0 -0
  78. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/MCP/__main__.py +0 -0
  79. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/MCP/client.py +0 -0
  80. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/MCP/server.py +0 -0
  81. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Metadata.py +0 -0
  82. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/MultiProc.py +0 -0
  83. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/OpenFIGI.py +0 -0
  84. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Redaction.py +0 -0
  85. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Routines/ArchiveOldCollections.py +0 -0
  86. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Routines/BatchJob.py +0 -0
  87. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Routines/ContainerHealth.py +0 -0
  88. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Routines/JobStore.py +0 -0
  89. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Routines/RoutineCommand.py +0 -0
  90. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Routines/RoutineOrigin.py +0 -0
  91. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Routines/Schedule.py +0 -0
  92. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Routines/ScheduleMirror.py +0 -0
  93. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Routines/ScheduleMonitor.py +0 -0
  94. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Routines/ScheduleStore.py +0 -0
  95. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Routines/Scheduler.py +0 -0
  96. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Routines/UpdateActiveJobs.py +0 -0
  97. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Routines/Worker.py +0 -0
  98. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Routines/WorkerBootstrap.py +0 -0
  99. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Routines/WorkerLib.py +0 -0
  100. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Routines/WorkerPool.py +0 -0
  101. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Routines/__init__.py +0 -0
  102. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/SQLite.py +0 -0
  103. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/SharedData.py +0 -0
  104. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/SharedNumpy.py +0 -0
  105. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/StreamKafka.py +0 -0
  106. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Symbol.py +0 -0
  107. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/TableIndex.py +0 -0
  108. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/TableIndexJitFunctions.py +0 -0
  109. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/TableIndexJitFunctionsManual.py +0 -0
  110. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/TableIndexJitGenerate.py +0 -0
  111. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/TableIndexJitHash.py +0 -0
  112. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/TableIndexJitLoc.py +0 -0
  113. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/TableRead.py +0 -0
  114. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/TimeSeriesDisk.py +0 -0
  115. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/TimeseriesContainer.py +0 -0
  116. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Users.py +0 -0
  117. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Utils.py +0 -0
  118. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/ADDING_A_PAGE.md +0 -0
  119. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/__init__.py +0 -0
  120. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/activity_logger.py +0 -0
  121. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/app.py +0 -0
  122. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/assets/dashAgGridComponentFunctions.js +0 -0
  123. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/assets/dashAgGridFunctions.js +0 -0
  124. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/assets/google_logo.png +0 -0
  125. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/assets/kafka_keys.js +0 -0
  126. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/assets/logs.css +0 -0
  127. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/assets/sched.css +0 -0
  128. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/assets/styles.css +0 -0
  129. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/auth.py +0 -0
  130. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/backends.py +0 -0
  131. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/config.py +0 -0
  132. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/containers.py +0 -0
  133. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/identity.py +0 -0
  134. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/kafka_view.py +0 -0
  135. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/mongo_view.py +0 -0
  136. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/proc.py +0 -0
  137. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/redis_view.py +0 -0
  138. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/route_health.py +0 -0
  139. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/route_registry.py +0 -0
  140. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/sched.py +0 -0
  141. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/schedule_editor.py +0 -0
  142. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/server.py +0 -0
  143. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/services.py +0 -0
  144. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/shell.py +0 -0
  145. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/standalone.py +0 -0
  146. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/static/account.js +0 -0
  147. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/static/custom.css +0 -0
  148. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/static/favicon.ico +0 -0
  149. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/static/favicon.png +0 -0
  150. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/static/logo.png +0 -0
  151. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/static/logo_96x96.png +0 -0
  152. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/static/shareddata-mark.svg +0 -0
  153. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/static/shell.css +0 -0
  154. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/static/shell.js +0 -0
  155. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/static/standalone.css +0 -0
  156. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/static/standalone.js +0 -0
  157. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/suggest.py +0 -0
  158. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/templates/account.html +0 -0
  159. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/templates/base.html +0 -0
  160. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/templates/claim.html +0 -0
  161. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/templates/claim_done.html +0 -0
  162. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/templates/dash.html +0 -0
  163. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/templates/index.html +0 -0
  164. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/templates/login.html +0 -0
  165. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/templates/login_2fa.html +0 -0
  166. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/templates/partials/navbar.html +0 -0
  167. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/templates/partials/scripts.html +0 -0
  168. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/templates/recovery_codes.html +0 -0
  169. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/templates/shell.html +0 -0
  170. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/templates/standalone.html +0 -0
  171. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/twofactor.py +0 -0
  172. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/utils.py +0 -0
  173. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/Web/workerpool.py +0 -0
  174. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/__init__.py +0 -0
  175. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/build_info.py +0 -0
  176. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/fleet.py +0 -0
  177. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/preflight.py +0 -0
  178. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/private_files.py +0 -0
  179. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/release_backup.py +0 -0
  180. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/server.py +0 -0
  181. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/services.py +0 -0
  182. {shareddata-6.85.9 → shareddata-6.85.11}/src/SharedData/sharedmutexwin.pyd +0 -0
  183. {shareddata-6.85.9 → shareddata-6.85.11}/src/shareddata.egg-info/SOURCES.txt +0 -0
  184. {shareddata-6.85.9 → shareddata-6.85.11}/src/shareddata.egg-info/dependency_links.txt +0 -0
  185. {shareddata-6.85.9 → shareddata-6.85.11}/src/shareddata.egg-info/entry_points.txt +0 -0
  186. {shareddata-6.85.9 → shareddata-6.85.11}/src/shareddata.egg-info/requires.txt +0 -0
  187. {shareddata-6.85.9 → shareddata-6.85.11}/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.9
3
+ Version: 6.85.11
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.9',
69
+ version='6.85.11',
70
70
  description='Memory Mapped / Shared Memory Database with S3 repository',
71
71
  author='shareddata',
72
72
  author_email='admin@shareddata.net',
@@ -321,7 +321,7 @@ class CollectionMongoDB:
321
321
  # Insert all prepared documents into the collection
322
322
  result = []
323
323
  if documents_to_insert:
324
- result = self._collection.insert_many(documents_to_insert)
324
+ result = self._collection.insert_many(documents_to_insert, ordered=False)
325
325
 
326
326
  return result
327
327
 
@@ -687,8 +687,18 @@ class Table:
687
687
  records, so they are removed and rebuilt from the new empty header.
688
688
  """
689
689
  from SharedData.TableRewrite import (RewriteError, fsync_directory,
690
- require_rewrite_support)
691
- require_rewrite_support()
690
+ rewrite_supported)
691
+ if not rewrite_supported():
692
+ # No POSIX rename-over-a-mapped-file: remove the old files (the shared mutex is held in STRUCT
693
+ # mode, so this process is their only user; another process that still maps one makes the
694
+ # unlink fail loudly) and create the empty image in place.
695
+ for name in ('data.bin', 'bson.bin', 'dateidx.bin', 'pkey.bin', 'symbolidx.bin', 'portidx.bin'):
696
+ try:
697
+ (self.filepath.parent / name).unlink()
698
+ except FileNotFoundError:
699
+ pass
700
+ self.malloc(create=True)
701
+ return
692
702
  final = self.filepath
693
703
  old = os.stat(final)
694
704
  # The writer lock is held: any earlier stage is from a build that died.
@@ -1659,6 +1669,10 @@ class Table:
1659
1669
 
1660
1670
  def compact_bson_if_worthwhile(self):
1661
1671
  """Compact the BSON file when enough of it is orphaned; None when it is not worth a rewrite."""
1672
+ if self.type == 1:
1673
+ from SharedData.TableRewrite import rewrite_supported
1674
+ if not rewrite_supported():
1675
+ return None # the pair publication needs POSIX file APIs; compaction only saves space
1662
1676
  usage = self.bson_usage()
1663
1677
  if usage['orphaned'] < BSON_DEFRAG_MIN_BYTES \
1664
1678
  or usage['orphaned'] < BSON_DEFRAG_MIN_FRACTION * max(usage['used'], 1):
@@ -1764,7 +1778,8 @@ class Table:
1764
1778
 
1765
1779
  with structure(self):
1766
1780
  publish_rewrite(self, None, 'defrag', start=0, transform=move_pointers,
1767
- header_updates={'next_bson_ptr': payload, 'mtime': max(datetime.now().timestamp(), float(self.hdr['mtime']) + 0.001)},
1781
+ header_updates={'next_bson_ptr': payload, 'mtime': max(datetime.now().timestamp(), float(self.hdr['mtime']) + 0.001),
1782
+ 'isidxcreated': int(self.hdr['isidxcreated'])}, # pointers only: the index stays valid
1768
1783
  bson=dict(token=token, stage=stage, sha256=digest.hexdigest(), size=new_size))
1769
1784
  stats = {'original_size': original_size, 'new_size': new_size,
1770
1785
  'reclaimed': original_size - new_size, 'live_bytes': payload, 'live_rows': int(len(live_idx))}
@@ -1819,6 +1834,10 @@ class Table:
1819
1834
  Exception: If the table is not schemaless or if defragmentation fails.
1820
1835
  """
1821
1836
  if self.type == 1:
1837
+ from SharedData.TableRewrite import rewrite_supported
1838
+ if not rewrite_supported():
1839
+ Logger.log.warning(f'{self.relpath} BSON not compacted: the pair publication needs POSIX file APIs')
1840
+ return {'original_size': 0, 'new_size': 0, 'reclaimed': 0}
1822
1841
  return self._defragment_bson_disk(chunk_size, acquire)
1823
1842
  if not self.is_schemaless:
1824
1843
  raise Exception(f'Cannot defragment non-schemaless table {self.relpath}')
@@ -3017,11 +3036,18 @@ class Table:
3017
3036
  self._set_mode(DIRTY)
3018
3037
  # A nested alias may follow a failed publication by this thread;
3019
3038
  # only an in-progress structural operation of this thread is STRUCT.
3039
+ self._rewrite_kept_index = False
3020
3040
  if self.type == 1 and mode(self.mutex['type']) != STRUCT:
3021
3041
  from SharedData.TableRewrite import recover_rewrite
3022
3042
  recover_rewrite(self)
3043
+ # A pending defrag descriptor means the dead holder was only in the defrag (one holder at a time, a
3044
+ # crashed upsert would have been repaired before it could start): keys and rows never moved, so the
3045
+ # index it left is valid and the dirty repair must not rebuild it (a rebuild can be refused).
3046
+ kept_index = getattr(self, '_rewrite_kept_index', False)
3023
3047
  self._refresh_mapping(dirty=dirty)
3024
- if dirty and self.hdr is not None:
3048
+ if kept_index and self.hasindex:
3049
+ self.index.rememmap() # keep the index, but map its files as they are now (the dirty refresh skips it)
3050
+ if dirty and self.hdr is not None and not kept_index:
3025
3051
  self.hdr['isidxcreated'] = 0
3026
3052
  if self.hasindex:
3027
3053
  self.index.initialize()
@@ -300,7 +300,12 @@ class TableDisk(Table):
300
300
  """
301
301
  if self.hdr['recordssize'] <= self.hdr['count']:
302
302
  return self
303
- from SharedData.TableRewrite import publish_rewrite
303
+ from SharedData.TableRewrite import publish_rewrite, rewrite_supported
304
+ if not rewrite_supported():
305
+ # Shrinking needs a second file replacing the mapped one (Linux). Trim only returns unused space,
306
+ # so the table is left as it is rather than failing.
307
+ Logger.log.warning('%s not trimmed: shrinking a disk table needs POSIX file APIs' % self.relpath)
308
+ return self
304
309
  return publish_rewrite(self, None, 'trim', capacity=max(2, int(self.hdr['count'])))
305
310
 
306
311
  ############### RELOAD ###############
@@ -154,9 +154,15 @@ def structure(table):
154
154
  try:
155
155
  yield
156
156
  except BaseException:
157
- table._set_mode(DIRTY)
158
- if table.hdr is not None:
159
- table.hdr['isidxcreated'] = 0
157
+ if getattr(table, '_rewrite_live_untouched', False):
158
+ # A defrag that failed before it replaced any live file: the table is exactly as it was, so it is
159
+ # neither dirty nor does its index need a rebuild (which a legacy table can refuse).
160
+ table._rewrite_live_untouched = False
161
+ table._set_mode(previous)
162
+ else:
163
+ table._set_mode(DIRTY)
164
+ if table.hdr is not None:
165
+ table.hdr['isidxcreated'] = 0
160
166
  raise
161
167
  else:
162
168
  word = int(table.mutex['type'])
@@ -38,14 +38,66 @@ def fsync_directory(path):
38
38
  os.close(fd)
39
39
 
40
40
 
41
+ def rewrite_supported():
42
+ """True where the staged, crash-safe rewrite can run (Linux POSIX APIs)."""
43
+ return sys.platform == 'linux' and all(hasattr(os, name) for name in (
44
+ 'O_DIRECTORY', 'fchown', 'fchmod', 'posix_fallocate',
45
+ 'listxattr', 'getxattr', 'setxattr'))
46
+
47
+
41
48
  def require_rewrite_support():
42
- if sys.platform != 'linux' or not all(hasattr(os, name) for name in (
43
- 'O_DIRECTORY', 'fchown', 'fchmod', 'posix_fallocate',
44
- 'listxattr', 'getxattr', 'setxattr')):
49
+ if not rewrite_supported():
45
50
  raise RewriteError('crash-safe disk record rewrites require Linux POSIX APIs; '
46
51
  'sort/trim/rewrite recovery is unsupported on this platform')
47
52
 
48
53
 
54
+ def _publish_in_place(table, order, operation, *, capacity, start, sorted_flag, header_updates, transform, bson):
55
+ """Platforms without the staged rewrite (Windows): permute the rows in the mapped image itself.
56
+
57
+ The shared mutex is held in STRUCT mode by the caller, so no other process or thread reads or writes
58
+ the table meanwhile and nothing needs a replacement file (which Windows could not even rename over a
59
+ mapped file). This is the pre-6.85 behaviour and it is NOT crash-safe: a crash inside the permutation
60
+ leaves a table the next owner finds in STRUCT mode, and it rebuilds the index, but it cannot undo a
61
+ half-moved row range. Only record-preserving operations (sort, cleanup) are supported here; whatever
62
+ needs a second file (trim, BSON pair) is refused.
63
+ """
64
+ if bson is not None or transform is not None or operation not in ('sort', 'cleanup'):
65
+ raise RewriteError(f'{operation} needs the staged rewrite, which requires Linux POSIX APIs')
66
+ if capacity is not None and int(capacity) != int(table.hdr['recordssize']):
67
+ raise RewriteError(f'{operation} with a new capacity needs the staged rewrite (Linux only)')
68
+ if table.type != 1 or not table._owns_lock():
69
+ raise RewriteError('disk record publication requires writer ownership')
70
+ table._sync_held_mapping()
71
+ old_count = int(table.hdr['count'])
72
+ rows = table.records.view(np.ndarray)
73
+ if len(rows) < old_count:
74
+ raise RewriteError('stale rewrite source bounds')
75
+ if order is None:
76
+ count = old_count
77
+ else:
78
+ order = np.asarray(order)
79
+ if np.any(order < 0) or np.any(order >= old_count):
80
+ raise RewriteError('replacement source out of range')
81
+ if operation == 'sort' and not np.array_equal(np.sort(order), np.arange(old_count)):
82
+ raise RewriteError('record-preserving rewrite requires a complete permutation')
83
+ count = len(order)
84
+ chosen = rows[order] # fancy indexing copies: safe to overwrite the source rows
85
+ rows[:count] = chosen
86
+ if count < old_count:
87
+ rows[count:old_count] = np.zeros((), dtype=rows.dtype)
88
+ table.hdr['count'] = count
89
+ table.hdr['isidxcreated'] = 0
90
+ if sorted_flag is not None:
91
+ table.hdr['isidxsorted'] = sorted_flag
92
+ table.hdr['minchgid'] = min(int(table.hdr['minchgid']), int(start))
93
+ for field, value in (header_updates or {}).items():
94
+ table.hdr[field] = value
95
+ table.shf_data.flush()
96
+ sync_header(table)
97
+ table.index.rebuild_index_only()
98
+ return table.records
99
+
100
+
49
101
  def sync_file(path):
50
102
  with open(path, 'r+b' if os.name == 'nt' else 'rb') as stream:
51
103
  os.fsync(stream.fileno())
@@ -190,6 +242,8 @@ def _load(table):
190
242
  raise ValueError('invalid BSON digest')
191
243
  elif 'bson' in descriptor:
192
244
  raise ValueError('BSON section requires version 2')
245
+ if 'index_valid' in descriptor and descriptor['index_valid'] not in (0, 1):
246
+ raise ValueError('invalid index validity')
193
247
  return descriptor
194
248
  except Exception as error:
195
249
  raise RewriteError('invalid pending record rewrite; files preserved') from error
@@ -208,10 +262,21 @@ def _finish(table, descriptor, recovery=False):
208
262
  if 'bson' in descriptor:
209
263
  table._reset_bson_mapping() # the BSON file was replaced together with the records
210
264
  checkpoint(prefix + 'data_attached')
211
- table.hdr['isidxcreated'] = 0
212
- sync_header(table)
265
+ # A defrag moves BSON pointers only: keys, row positions and so every index file stay valid and mapped.
266
+ # initialize() always resets and rebuilds the index, and the rebuild refuses legacy tables with an
267
+ # empty-key row ("explicit cleanup required"), so a defrag neither invalidates nor rebuilds it.
268
+ keeps_index = descriptor.get('operation') == 'defrag'
269
+ table._rewrite_kept_index = keeps_index # acquire(): a dirty owner that just finished such a recovery must not rebuild
270
+ if not keeps_index:
271
+ table.hdr['isidxcreated'] = 0
272
+ sync_header(table)
273
+ elif descriptor.get('index_valid') is not None and int(table.hdr['isidxcreated']) != descriptor['index_valid']:
274
+ # structure() clears the bit when a failure follows the attach: the index files never changed, so the
275
+ # validity they had before the defrag is restored (descriptors of older releases do not carry it).
276
+ table.hdr['isidxcreated'] = descriptor['index_valid']
277
+ sync_header(table)
213
278
  checkpoint(prefix + 'index_invalid_synced')
214
- if table.hasindex:
279
+ if table.hasindex and not keeps_index:
215
280
  table.index.initialize()
216
281
  sync_header(table)
217
282
  checkpoint(prefix + 'final_header_synced')
@@ -312,11 +377,16 @@ def publish_rewrite(table, order, operation, *, capacity=None, start=0, sorted_f
312
377
  names a complete, synced BSON replacement built beside bson.bin: both files are then published as a pair
313
378
  (BSON first, records second, a version 2 descriptor makes the pair recoverable).
314
379
  """
315
- require_rewrite_support()
380
+ if not rewrite_supported():
381
+ return _publish_in_place(table, order, operation, capacity=capacity, start=start, sorted_flag=sorted_flag,
382
+ header_updates=header_updates, transform=transform, bson=bson)
316
383
  if table.type != 1 or not table._owns_lock():
317
384
  raise RewriteError('disk record publication requires writer ownership')
318
385
  if pending_path(table).exists():
319
386
  raise RewriteError('unresolved record rewrite')
387
+ # Until the first live file is replaced a failing defrag leaves the table untouched (structure() then
388
+ # restores the mode instead of marking it dirty).
389
+ table._rewrite_live_untouched = operation == 'defrag'
320
390
  checkpoint('struct_enter')
321
391
  table.shf_data.flush()
322
392
  sync_header(table)
@@ -393,6 +463,8 @@ def publish_rewrite(table, order, operation, *, capacity=None, start=0, sorted_f
393
463
  transaction=token, table=str(table.relpath).replace('\\', '/'),
394
464
  operation=operation, start=int(start), stage=stage.name,
395
465
  old=old, new=new)
466
+ if operation == 'defrag':
467
+ descriptor['index_valid'] = int(table.hdr['isidxcreated'])
396
468
  if bson:
397
469
  bson_stage = Path(table.bsonpath).parent / ('bson.bin.stage.' + token)
398
470
  if not bson_stage.is_file() or bson_stage.stat().st_size != bson['size']:
@@ -412,6 +484,7 @@ def publish_rewrite(table, order, operation, *, capacity=None, start=0, sorted_f
412
484
  checkpoint('prepare_installed')
413
485
  fsync_directory(stage.parent)
414
486
  checkpoint('prepare_dir_synced')
487
+ table._rewrite_live_untouched = False # from the first replacement on, recovery and DIRTY apply
415
488
  if bson:
416
489
  os.replace(bson_stage, table.bsonpath)
417
490
  checkpoint('bson_replaced')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: shareddata
3
- Version: 6.85.9
3
+ Version: 6.85.11
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