lmcache-cli 0.4.5.dev0__py3-none-any.whl

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 (399) hide show
  1. lmcache/__init__.py +84 -0
  2. lmcache/_version.py +24 -0
  3. lmcache/cli/__init__.py +1 -0
  4. lmcache/cli/commands/__init__.py +34 -0
  5. lmcache/cli/commands/base.py +157 -0
  6. lmcache/cli/commands/bench/__init__.py +557 -0
  7. lmcache/cli/commands/bench/engine_bench/__init__.py +1 -0
  8. lmcache/cli/commands/bench/engine_bench/config.py +245 -0
  9. lmcache/cli/commands/bench/engine_bench/interactive/__init__.py +274 -0
  10. lmcache/cli/commands/bench/engine_bench/interactive/config.json +10 -0
  11. lmcache/cli/commands/bench/engine_bench/interactive/schema.py +352 -0
  12. lmcache/cli/commands/bench/engine_bench/interactive/state.py +327 -0
  13. lmcache/cli/commands/bench/engine_bench/interactive/terminal.py +291 -0
  14. lmcache/cli/commands/bench/engine_bench/progress.py +145 -0
  15. lmcache/cli/commands/bench/engine_bench/request_sender.py +232 -0
  16. lmcache/cli/commands/bench/engine_bench/stats.py +275 -0
  17. lmcache/cli/commands/bench/engine_bench/workloads/__init__.py +153 -0
  18. lmcache/cli/commands/bench/engine_bench/workloads/base.py +122 -0
  19. lmcache/cli/commands/bench/engine_bench/workloads/long_doc_permutator.py +435 -0
  20. lmcache/cli/commands/bench/engine_bench/workloads/long_doc_qa.py +281 -0
  21. lmcache/cli/commands/bench/engine_bench/workloads/multi_round_chat.py +337 -0
  22. lmcache/cli/commands/bench/engine_bench/workloads/random_prefill.py +178 -0
  23. lmcache/cli/commands/describe.py +310 -0
  24. lmcache/cli/commands/kvcache.py +133 -0
  25. lmcache/cli/commands/mock.py +75 -0
  26. lmcache/cli/commands/ping.py +113 -0
  27. lmcache/cli/commands/query/__init__.py +155 -0
  28. lmcache/cli/commands/query/prompt.py +134 -0
  29. lmcache/cli/commands/query/request.py +357 -0
  30. lmcache/cli/commands/server.py +99 -0
  31. lmcache/cli/commands/tool/__init__.py +63 -0
  32. lmcache/cli/commands/tool/cache_simulator.py +113 -0
  33. lmcache/cli/commands/trace/__init__.py +505 -0
  34. lmcache/cli/commands/trace/dispatch.py +249 -0
  35. lmcache/cli/commands/trace/driver.py +372 -0
  36. lmcache/cli/commands/trace/stats.py +289 -0
  37. lmcache/cli/documents/lmcache.txt +11 -0
  38. lmcache/cli/main.py +42 -0
  39. lmcache/cli/metrics/__init__.py +29 -0
  40. lmcache/cli/metrics/formatter.py +171 -0
  41. lmcache/cli/metrics/handler.py +94 -0
  42. lmcache/cli/metrics/metrics.py +161 -0
  43. lmcache/cli/metrics/section.py +77 -0
  44. lmcache/connections.py +173 -0
  45. lmcache/integration/__init__.py +2 -0
  46. lmcache/integration/base_service_factory.py +165 -0
  47. lmcache/integration/request_telemetry/__init__.py +1 -0
  48. lmcache/integration/request_telemetry/base.py +51 -0
  49. lmcache/integration/request_telemetry/factory.py +113 -0
  50. lmcache/integration/request_telemetry/fastapi.py +109 -0
  51. lmcache/integration/request_telemetry/noop.py +35 -0
  52. lmcache/integration/sglang/__init__.py +2 -0
  53. lmcache/integration/sglang/sglang_adapter.py +326 -0
  54. lmcache/integration/sglang/utils.py +39 -0
  55. lmcache/integration/vllm/__init__.py +1 -0
  56. lmcache/integration/vllm/lmcache_connector_v1.py +213 -0
  57. lmcache/integration/vllm/lmcache_connector_v1_085.py +150 -0
  58. lmcache/integration/vllm/lmcache_mp_connector_0180.py +1072 -0
  59. lmcache/integration/vllm/tests/test_mm_hash_utils.py +112 -0
  60. lmcache/integration/vllm/utils.py +433 -0
  61. lmcache/integration/vllm/vllm_multi_process_adapter.py +1090 -0
  62. lmcache/integration/vllm/vllm_service_factory.py +339 -0
  63. lmcache/integration/vllm/vllm_v1_adapter.py +1713 -0
  64. lmcache/logging.py +107 -0
  65. lmcache/native_storage_ops.pyi +230 -0
  66. lmcache/non_cuda_equivalents.py +1424 -0
  67. lmcache/observability.py +1958 -0
  68. lmcache/storage_backend/serde/__init__.py +1 -0
  69. lmcache/storage_backend/serde/cachegen_basics.py +210 -0
  70. lmcache/storage_backend/serde/cachegen_decoder.py +207 -0
  71. lmcache/storage_backend/serde/cachegen_encoder.py +394 -0
  72. lmcache/storage_backend/serde/serde.py +75 -0
  73. lmcache/tools/__init__.py +1 -0
  74. lmcache/tools/cache_simulator/README.md +392 -0
  75. lmcache/tools/cache_simulator/__init__.py +1 -0
  76. lmcache/tools/cache_simulator/docs/simulate_example.png +0 -0
  77. lmcache/tools/cache_simulator/docs/sweep_example.png +0 -0
  78. lmcache/tools/cache_simulator/gen_bench_dataset.py +360 -0
  79. lmcache/tools/cache_simulator/lru_cache.py +124 -0
  80. lmcache/tools/cache_simulator/plot_hit_rate.py +231 -0
  81. lmcache/tools/cache_simulator/simulator.py +795 -0
  82. lmcache/tools/controller_benchmark/README.md +161 -0
  83. lmcache/tools/controller_benchmark/__init__.py +1 -0
  84. lmcache/tools/controller_benchmark/__main__.py +331 -0
  85. lmcache/tools/controller_benchmark/benchmark.py +660 -0
  86. lmcache/tools/controller_benchmark/config.py +44 -0
  87. lmcache/tools/controller_benchmark/constants.py +10 -0
  88. lmcache/tools/controller_benchmark/handlers/__init__.py +46 -0
  89. lmcache/tools/controller_benchmark/handlers/admit.py +52 -0
  90. lmcache/tools/controller_benchmark/handlers/base.py +47 -0
  91. lmcache/tools/controller_benchmark/handlers/deregister.py +49 -0
  92. lmcache/tools/controller_benchmark/handlers/evict.py +52 -0
  93. lmcache/tools/controller_benchmark/handlers/heartbeat.py +56 -0
  94. lmcache/tools/controller_benchmark/handlers/p2p_lookup.py +47 -0
  95. lmcache/tools/controller_benchmark/handlers/register.py +56 -0
  96. lmcache/tools/mp_status_viewer/__init__.py +1 -0
  97. lmcache/tools/mp_status_viewer/__main__.py +95 -0
  98. lmcache/usage_context.py +417 -0
  99. lmcache/utils.py +665 -0
  100. lmcache/v1/__init__.py +2 -0
  101. lmcache/v1/api_server/__init__.py +2 -0
  102. lmcache/v1/api_server/__main__.py +537 -0
  103. lmcache/v1/basic_check.py +112 -0
  104. lmcache/v1/cache_controller/__init__.py +9 -0
  105. lmcache/v1/cache_controller/commands/__init__.py +15 -0
  106. lmcache/v1/cache_controller/commands/base.py +35 -0
  107. lmcache/v1/cache_controller/commands/full_sync.py +49 -0
  108. lmcache/v1/cache_controller/config.py +176 -0
  109. lmcache/v1/cache_controller/controller_manager.py +535 -0
  110. lmcache/v1/cache_controller/controllers/__init__.py +11 -0
  111. lmcache/v1/cache_controller/controllers/full_sync_tracker.py +473 -0
  112. lmcache/v1/cache_controller/controllers/kv_controller.py +439 -0
  113. lmcache/v1/cache_controller/controllers/registration_controller.py +282 -0
  114. lmcache/v1/cache_controller/executor.py +463 -0
  115. lmcache/v1/cache_controller/frontend/static/css/style.css +201 -0
  116. lmcache/v1/cache_controller/frontend/static/img/logo.png +0 -0
  117. lmcache/v1/cache_controller/frontend/static/index.html +234 -0
  118. lmcache/v1/cache_controller/frontend/static/js/controller_app.js +660 -0
  119. lmcache/v1/cache_controller/full_sync_sender.py +475 -0
  120. lmcache/v1/cache_controller/locks.py +149 -0
  121. lmcache/v1/cache_controller/message.py +828 -0
  122. lmcache/v1/cache_controller/observability.py +208 -0
  123. lmcache/v1/cache_controller/utils.py +679 -0
  124. lmcache/v1/cache_controller/worker.py +665 -0
  125. lmcache/v1/cache_engine.py +2058 -0
  126. lmcache/v1/cache_interface.py +19 -0
  127. lmcache/v1/check/__init__.py +74 -0
  128. lmcache/v1/check/check_mode_gen.py +86 -0
  129. lmcache/v1/check/check_mode_test_l2_adapter.py +284 -0
  130. lmcache/v1/check/check_mode_test_remote.py +155 -0
  131. lmcache/v1/check/check_mode_test_storage_manager.py +142 -0
  132. lmcache/v1/check/utils.py +571 -0
  133. lmcache/v1/compute/__init__.py +2 -0
  134. lmcache/v1/compute/attention/__init__.py +0 -0
  135. lmcache/v1/compute/attention/abstract.py +39 -0
  136. lmcache/v1/compute/attention/flash_attn.py +129 -0
  137. lmcache/v1/compute/attention/flash_infer_sparse.py +284 -0
  138. lmcache/v1/compute/attention/metadata.py +85 -0
  139. lmcache/v1/compute/attention/utils.py +14 -0
  140. lmcache/v1/compute/blend/__init__.py +7 -0
  141. lmcache/v1/compute/blend/blender.py +168 -0
  142. lmcache/v1/compute/blend/metadata.py +34 -0
  143. lmcache/v1/compute/blend/utils.py +63 -0
  144. lmcache/v1/compute/models/__init__.py +0 -0
  145. lmcache/v1/compute/models/base.py +141 -0
  146. lmcache/v1/compute/models/llama.py +9 -0
  147. lmcache/v1/compute/models/qwen3.py +24 -0
  148. lmcache/v1/compute/models/utils.py +68 -0
  149. lmcache/v1/compute/positional_encoding.py +199 -0
  150. lmcache/v1/config.py +848 -0
  151. lmcache/v1/config_base.py +848 -0
  152. lmcache/v1/distributed/api.py +248 -0
  153. lmcache/v1/distributed/config.py +321 -0
  154. lmcache/v1/distributed/error.py +64 -0
  155. lmcache/v1/distributed/eviction.py +192 -0
  156. lmcache/v1/distributed/eviction_policy/__init__.py +21 -0
  157. lmcache/v1/distributed/eviction_policy/factory.py +27 -0
  158. lmcache/v1/distributed/eviction_policy/lru.py +244 -0
  159. lmcache/v1/distributed/eviction_policy/noop.py +50 -0
  160. lmcache/v1/distributed/internal_api.py +170 -0
  161. lmcache/v1/distributed/l1_manager.py +835 -0
  162. lmcache/v1/distributed/l2_adapters/__init__.py +67 -0
  163. lmcache/v1/distributed/l2_adapters/base.py +360 -0
  164. lmcache/v1/distributed/l2_adapters/config.py +385 -0
  165. lmcache/v1/distributed/l2_adapters/factory.py +205 -0
  166. lmcache/v1/distributed/l2_adapters/fs_l2_adapter.py +747 -0
  167. lmcache/v1/distributed/l2_adapters/fs_native_l2_adapter.py +167 -0
  168. lmcache/v1/distributed/l2_adapters/mock_l2_adapter.py +516 -0
  169. lmcache/v1/distributed/l2_adapters/mooncake_store_l2_adapter.py +135 -0
  170. lmcache/v1/distributed/l2_adapters/native_connector_l2_adapter.py +468 -0
  171. lmcache/v1/distributed/l2_adapters/native_plugin_l2_adapter.py +199 -0
  172. lmcache/v1/distributed/l2_adapters/nixl_store_dynamic_l2_adapter.py +831 -0
  173. lmcache/v1/distributed/l2_adapters/nixl_store_l2_adapter.py +983 -0
  174. lmcache/v1/distributed/l2_adapters/plugin_l2_adapter.py +210 -0
  175. lmcache/v1/distributed/l2_adapters/resp_l2_adapter.py +176 -0
  176. lmcache/v1/distributed/memory_manager.py +179 -0
  177. lmcache/v1/distributed/storage_controller.py +39 -0
  178. lmcache/v1/distributed/storage_controllers/__init__.py +43 -0
  179. lmcache/v1/distributed/storage_controllers/eviction_controller.py +242 -0
  180. lmcache/v1/distributed/storage_controllers/prefetch_controller.py +830 -0
  181. lmcache/v1/distributed/storage_controllers/prefetch_policy.py +193 -0
  182. lmcache/v1/distributed/storage_controllers/store_controller.py +452 -0
  183. lmcache/v1/distributed/storage_controllers/store_policy.py +213 -0
  184. lmcache/v1/distributed/storage_manager.py +532 -0
  185. lmcache/v1/event_manager.py +145 -0
  186. lmcache/v1/exceptions/__init__.py +16 -0
  187. lmcache/v1/gpu_connector/__init__.py +126 -0
  188. lmcache/v1/gpu_connector/gpu_connectors.py +1906 -0
  189. lmcache/v1/gpu_connector/gpu_ops.py +85 -0
  190. lmcache/v1/gpu_connector/hpu_connector.py +326 -0
  191. lmcache/v1/gpu_connector/mock_gpu_connector.py +67 -0
  192. lmcache/v1/gpu_connector/utils.py +890 -0
  193. lmcache/v1/gpu_connector/xpu_connectors.py +916 -0
  194. lmcache/v1/health_monitor/__init__.py +1 -0
  195. lmcache/v1/health_monitor/base.py +587 -0
  196. lmcache/v1/health_monitor/checks/__init__.py +1 -0
  197. lmcache/v1/health_monitor/checks/remote_backend_check.py +304 -0
  198. lmcache/v1/health_monitor/constants.py +36 -0
  199. lmcache/v1/internal_api_server/__init__.py +0 -0
  200. lmcache/v1/internal_api_server/api_registry.py +59 -0
  201. lmcache/v1/internal_api_server/api_server.py +120 -0
  202. lmcache/v1/internal_api_server/common/__init__.py +1 -0
  203. lmcache/v1/internal_api_server/common/env_api.py +22 -0
  204. lmcache/v1/internal_api_server/common/loglevel_api.py +57 -0
  205. lmcache/v1/internal_api_server/common/metrics_api.py +29 -0
  206. lmcache/v1/internal_api_server/common/periodic_thread_api.py +138 -0
  207. lmcache/v1/internal_api_server/common/run_script_api.py +73 -0
  208. lmcache/v1/internal_api_server/common/thread_api.py +63 -0
  209. lmcache/v1/internal_api_server/controller/__init__.py +1 -0
  210. lmcache/v1/internal_api_server/controller/key_stats_api.py +81 -0
  211. lmcache/v1/internal_api_server/controller/worker_info_api.py +136 -0
  212. lmcache/v1/internal_api_server/utils.py +43 -0
  213. lmcache/v1/internal_api_server/vllm/__init__.py +1 -0
  214. lmcache/v1/internal_api_server/vllm/backend_api.py +221 -0
  215. lmcache/v1/internal_api_server/vllm/bypass_api.py +204 -0
  216. lmcache/v1/internal_api_server/vllm/cache_api.py +895 -0
  217. lmcache/v1/internal_api_server/vllm/chunk_statistics_api.py +141 -0
  218. lmcache/v1/internal_api_server/vllm/conf_api.py +147 -0
  219. lmcache/v1/internal_api_server/vllm/freeze_api.py +172 -0
  220. lmcache/v1/internal_api_server/vllm/hot_cache_api.py +184 -0
  221. lmcache/v1/internal_api_server/vllm/inference_api.py +65 -0
  222. lmcache/v1/internal_api_server/vllm/load_fs_chunks_api.py +320 -0
  223. lmcache/v1/internal_api_server/vllm/lookup_api.py +145 -0
  224. lmcache/v1/internal_api_server/vllm/version_api.py +25 -0
  225. lmcache/v1/kv_layer_groups.py +267 -0
  226. lmcache/v1/lazy_memory_allocator.py +284 -0
  227. lmcache/v1/lookup_client/__init__.py +25 -0
  228. lmcache/v1/lookup_client/abstract_client.py +77 -0
  229. lmcache/v1/lookup_client/async_lookup_message.py +50 -0
  230. lmcache/v1/lookup_client/chunk_statistics_lookup_client.py +200 -0
  231. lmcache/v1/lookup_client/factory.py +251 -0
  232. lmcache/v1/lookup_client/hit_limit_lookup_client.py +86 -0
  233. lmcache/v1/lookup_client/lmcache_async_lookup_client.py +407 -0
  234. lmcache/v1/lookup_client/lmcache_lookup_client.py +285 -0
  235. lmcache/v1/lookup_client/lmcache_lookup_client_bypass.py +99 -0
  236. lmcache/v1/lookup_client/mooncake_lookup_client.py +87 -0
  237. lmcache/v1/lookup_client/record_strategies/__init__.py +77 -0
  238. lmcache/v1/lookup_client/record_strategies/base.py +327 -0
  239. lmcache/v1/lookup_client/record_strategies/file_hash.py +130 -0
  240. lmcache/v1/lookup_client/record_strategies/memory_bloom_filter.py +81 -0
  241. lmcache/v1/manager.py +539 -0
  242. lmcache/v1/memory_management.py +2619 -0
  243. lmcache/v1/metadata.py +114 -0
  244. lmcache/v1/mp_observability/AGENTS.override.md +21 -0
  245. lmcache/v1/mp_observability/README.md +204 -0
  246. lmcache/v1/mp_observability/config.py +340 -0
  247. lmcache/v1/mp_observability/event.py +100 -0
  248. lmcache/v1/mp_observability/event_bus.py +313 -0
  249. lmcache/v1/mp_observability/otel_init.py +145 -0
  250. lmcache/v1/mp_observability/subscribers/__init__.py +28 -0
  251. lmcache/v1/mp_observability/subscribers/logging/__init__.py +19 -0
  252. lmcache/v1/mp_observability/subscribers/logging/l1.py +56 -0
  253. lmcache/v1/mp_observability/subscribers/logging/l2.py +73 -0
  254. lmcache/v1/mp_observability/subscribers/logging/lookup_hash.py +209 -0
  255. lmcache/v1/mp_observability/subscribers/logging/mp_server.py +90 -0
  256. lmcache/v1/mp_observability/subscribers/logging/sm.py +59 -0
  257. lmcache/v1/mp_observability/subscribers/metrics/__init__.py +20 -0
  258. lmcache/v1/mp_observability/subscribers/metrics/l0_lifecycle.py +290 -0
  259. lmcache/v1/mp_observability/subscribers/metrics/l1.py +55 -0
  260. lmcache/v1/mp_observability/subscribers/metrics/l1_lifecycle.py +166 -0
  261. lmcache/v1/mp_observability/subscribers/metrics/l2.py +121 -0
  262. lmcache/v1/mp_observability/subscribers/metrics/sm.py +69 -0
  263. lmcache/v1/mp_observability/subscribers/tracing/__init__.py +12 -0
  264. lmcache/v1/mp_observability/subscribers/tracing/mp_server.py +333 -0
  265. lmcache/v1/mp_observability/subscribers/tracing/span_registry.py +148 -0
  266. lmcache/v1/mp_observability/trace/__init__.py +50 -0
  267. lmcache/v1/mp_observability/trace/codecs.py +255 -0
  268. lmcache/v1/mp_observability/trace/decorator.py +147 -0
  269. lmcache/v1/mp_observability/trace/format.py +132 -0
  270. lmcache/v1/mp_observability/trace/lifecycle.py +83 -0
  271. lmcache/v1/mp_observability/trace/reader.py +167 -0
  272. lmcache/v1/mp_observability/trace/recorder.py +300 -0
  273. lmcache/v1/multiprocess/__init__.py +0 -0
  274. lmcache/v1/multiprocess/affinity_pool.py +102 -0
  275. lmcache/v1/multiprocess/blend_server_v2.py +891 -0
  276. lmcache/v1/multiprocess/config.py +253 -0
  277. lmcache/v1/multiprocess/custom_types.py +281 -0
  278. lmcache/v1/multiprocess/futures.py +194 -0
  279. lmcache/v1/multiprocess/gpu_context.py +511 -0
  280. lmcache/v1/multiprocess/http_server.py +235 -0
  281. lmcache/v1/multiprocess/mp_runtime_plugin_launcher.py +130 -0
  282. lmcache/v1/multiprocess/mq.py +732 -0
  283. lmcache/v1/multiprocess/protocol.py +86 -0
  284. lmcache/v1/multiprocess/protocols/README.md +213 -0
  285. lmcache/v1/multiprocess/protocols/__init__.py +127 -0
  286. lmcache/v1/multiprocess/protocols/base.py +89 -0
  287. lmcache/v1/multiprocess/protocols/blend.py +109 -0
  288. lmcache/v1/multiprocess/protocols/blend_v2.py +57 -0
  289. lmcache/v1/multiprocess/protocols/controller.py +53 -0
  290. lmcache/v1/multiprocess/protocols/debug.py +34 -0
  291. lmcache/v1/multiprocess/protocols/engine.py +146 -0
  292. lmcache/v1/multiprocess/protocols/observability.py +39 -0
  293. lmcache/v1/multiprocess/server.py +1134 -0
  294. lmcache/v1/multiprocess/session.py +190 -0
  295. lmcache/v1/multiprocess/token_hasher.py +441 -0
  296. lmcache/v1/offload_server/__init__.py +17 -0
  297. lmcache/v1/offload_server/abstract_server.py +37 -0
  298. lmcache/v1/offload_server/message.py +30 -0
  299. lmcache/v1/offload_server/zmq_server.py +122 -0
  300. lmcache/v1/periodic_thread.py +579 -0
  301. lmcache/v1/pin_monitor.py +246 -0
  302. lmcache/v1/plugin/__init__.py +0 -0
  303. lmcache/v1/plugin/runtime_plugin_launcher.py +211 -0
  304. lmcache/v1/protocol.py +317 -0
  305. lmcache/v1/rpc/__init__.py +17 -0
  306. lmcache/v1/rpc/transport.py +105 -0
  307. lmcache/v1/rpc/zmq_transport.py +213 -0
  308. lmcache/v1/rpc_utils.py +165 -0
  309. lmcache/v1/server/__init__.py +2 -0
  310. lmcache/v1/server/__main__.py +170 -0
  311. lmcache/v1/server/storage_backend/__init__.py +21 -0
  312. lmcache/v1/server/storage_backend/abstract_backend.py +80 -0
  313. lmcache/v1/server/storage_backend/local_backend.py +75 -0
  314. lmcache/v1/server/utils.py +21 -0
  315. lmcache/v1/standalone/__init__.py +1 -0
  316. lmcache/v1/standalone/__main__.py +583 -0
  317. lmcache/v1/standalone/manager.py +80 -0
  318. lmcache/v1/standalone/standalone_service_factory.py +86 -0
  319. lmcache/v1/storage_backend/__init__.py +313 -0
  320. lmcache/v1/storage_backend/abstract_backend.py +445 -0
  321. lmcache/v1/storage_backend/audit_backend.py +233 -0
  322. lmcache/v1/storage_backend/batched_message_sender.py +222 -0
  323. lmcache/v1/storage_backend/cache_policy/__init__.py +45 -0
  324. lmcache/v1/storage_backend/cache_policy/base_policy.py +87 -0
  325. lmcache/v1/storage_backend/cache_policy/fifo.py +58 -0
  326. lmcache/v1/storage_backend/cache_policy/lfu.py +105 -0
  327. lmcache/v1/storage_backend/cache_policy/lru.py +81 -0
  328. lmcache/v1/storage_backend/cache_policy/mru.py +61 -0
  329. lmcache/v1/storage_backend/connector/__init__.py +443 -0
  330. lmcache/v1/storage_backend/connector/audit_adapter.py +77 -0
  331. lmcache/v1/storage_backend/connector/audit_connector.py +320 -0
  332. lmcache/v1/storage_backend/connector/base_connector.py +379 -0
  333. lmcache/v1/storage_backend/connector/blackhole_adapter.py +21 -0
  334. lmcache/v1/storage_backend/connector/blackhole_connector.py +37 -0
  335. lmcache/v1/storage_backend/connector/eic_adapter.py +31 -0
  336. lmcache/v1/storage_backend/connector/eic_connector.py +757 -0
  337. lmcache/v1/storage_backend/connector/external_adapter.py +79 -0
  338. lmcache/v1/storage_backend/connector/fs_adapter.py +51 -0
  339. lmcache/v1/storage_backend/connector/fs_connector.py +403 -0
  340. lmcache/v1/storage_backend/connector/infinistore_adapter.py +56 -0
  341. lmcache/v1/storage_backend/connector/infinistore_connector.py +177 -0
  342. lmcache/v1/storage_backend/connector/instrumented_connector.py +219 -0
  343. lmcache/v1/storage_backend/connector/lm_adapter.py +31 -0
  344. lmcache/v1/storage_backend/connector/lm_connector.py +176 -0
  345. lmcache/v1/storage_backend/connector/mock_adapter.py +57 -0
  346. lmcache/v1/storage_backend/connector/mock_connector.py +349 -0
  347. lmcache/v1/storage_backend/connector/mooncakestore_adapter.py +43 -0
  348. lmcache/v1/storage_backend/connector/mooncakestore_connector.py +614 -0
  349. lmcache/v1/storage_backend/connector/redis_adapter.py +181 -0
  350. lmcache/v1/storage_backend/connector/redis_connector.py +828 -0
  351. lmcache/v1/storage_backend/connector/s3_adapter.py +59 -0
  352. lmcache/v1/storage_backend/connector/s3_connector.py +699 -0
  353. lmcache/v1/storage_backend/connector/sagemaker_hyperpod_adapter.py +233 -0
  354. lmcache/v1/storage_backend/connector/sagemaker_hyperpod_connector.py +987 -0
  355. lmcache/v1/storage_backend/connector/valkey_adapter.py +114 -0
  356. lmcache/v1/storage_backend/connector/valkey_connector.py +627 -0
  357. lmcache/v1/storage_backend/gds_backend.py +1199 -0
  358. lmcache/v1/storage_backend/job_executor/__init__.py +0 -0
  359. lmcache/v1/storage_backend/job_executor/base_executor.py +34 -0
  360. lmcache/v1/storage_backend/job_executor/pq_executor.py +235 -0
  361. lmcache/v1/storage_backend/local_cpu_backend.py +810 -0
  362. lmcache/v1/storage_backend/local_disk_backend.py +656 -0
  363. lmcache/v1/storage_backend/maru_backend.py +734 -0
  364. lmcache/v1/storage_backend/naive_serde/__init__.py +50 -0
  365. lmcache/v1/storage_backend/naive_serde/cachegen_basics.py +133 -0
  366. lmcache/v1/storage_backend/naive_serde/cachegen_decoder.py +135 -0
  367. lmcache/v1/storage_backend/naive_serde/cachegen_encoder.py +83 -0
  368. lmcache/v1/storage_backend/naive_serde/kivi_serde.py +22 -0
  369. lmcache/v1/storage_backend/naive_serde/naive_serde.py +18 -0
  370. lmcache/v1/storage_backend/naive_serde/serde.py +37 -0
  371. lmcache/v1/storage_backend/native_clients/connector_client_base.py +165 -0
  372. lmcache/v1/storage_backend/native_clients/resp_client.py +35 -0
  373. lmcache/v1/storage_backend/nixl_storage_backend.py +1400 -0
  374. lmcache/v1/storage_backend/p2p_backend.py +788 -0
  375. lmcache/v1/storage_backend/path_sharder.py +117 -0
  376. lmcache/v1/storage_backend/pd_backend.py +646 -0
  377. lmcache/v1/storage_backend/plugins/dax_backend.py +1443 -0
  378. lmcache/v1/storage_backend/plugins/rust_raw_block_backend.py +1361 -0
  379. lmcache/v1/storage_backend/remote_backend.py +624 -0
  380. lmcache/v1/storage_backend/resp_client.py +227 -0
  381. lmcache/v1/storage_backend/storage_backend_listener.py +19 -0
  382. lmcache/v1/storage_backend/storage_manager.py +1352 -0
  383. lmcache/v1/system_detection.py +110 -0
  384. lmcache/v1/token_database.py +551 -0
  385. lmcache/v1/transfer_channel/__init__.py +83 -0
  386. lmcache/v1/transfer_channel/abstract.py +285 -0
  387. lmcache/v1/transfer_channel/mock_memory_channel.py +156 -0
  388. lmcache/v1/transfer_channel/nixl_channel.py +639 -0
  389. lmcache/v1/transfer_channel/py_socket_channel.py +260 -0
  390. lmcache/v1/transfer_channel/transfer_utils.py +63 -0
  391. lmcache/v1/utils/__init__.py +1 -0
  392. lmcache/v1/utils/bloom_filter.py +109 -0
  393. lmcache/v1/utils/cache_utils.py +125 -0
  394. lmcache_cli-0.4.5.dev0.dist-info/METADATA +185 -0
  395. lmcache_cli-0.4.5.dev0.dist-info/RECORD +399 -0
  396. lmcache_cli-0.4.5.dev0.dist-info/WHEEL +5 -0
  397. lmcache_cli-0.4.5.dev0.dist-info/entry_points.txt +2 -0
  398. lmcache_cli-0.4.5.dev0.dist-info/licenses/LICENSE +201 -0
  399. lmcache_cli-0.4.5.dev0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,246 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Standard
3
+ from contextlib import nullcontext
4
+ from typing import TYPE_CHECKING, Optional
5
+ import threading
6
+ import time
7
+
8
+ # First Party
9
+ from lmcache.logging import init_logger
10
+ from lmcache.observability import LMCStatsMonitor, PrometheusLogger
11
+ from lmcache.v1.periodic_thread import (
12
+ PeriodicThread,
13
+ PeriodicThreadRegistry,
14
+ ThreadLevel,
15
+ ThreadRunSummary,
16
+ )
17
+
18
+ if TYPE_CHECKING:
19
+ # First Party
20
+ from lmcache.v1.config import LMCacheEngineConfig
21
+ from lmcache.v1.memory_management import MemoryObj
22
+
23
+
24
+ logger = init_logger(__name__)
25
+
26
+
27
+ class PinMonitor(PeriodicThread):
28
+ """
29
+ Global monitor (singleton per process, shared across all cache engines)
30
+ for pinned TensorMemoryObj instances to handle timeout detection.
31
+ This class runs a background thread that periodically checks for pinned objects
32
+ that have exceeded their timeout duration.
33
+ """
34
+
35
+ _instance = None
36
+ _instance_lock = threading.Lock() # Class-level lock for singleton pattern
37
+
38
+ def __init__(self, config: "LMCacheEngineConfig"):
39
+ # Initialize PeriodicThread base class
40
+ super().__init__(
41
+ name="PinMonitor-thread",
42
+ interval=config.pin_check_interval_sec,
43
+ level=ThreadLevel.CRITICAL,
44
+ init_wait=0.0,
45
+ )
46
+
47
+ # obj_id is the virtual memory address given by Python's id() function
48
+ self._pinned_objects: dict[
49
+ int, tuple["MemoryObj", float]
50
+ ] = {} # {obj_id: (memory_obj, register_time)}
51
+ self._objects_lock = threading.Lock()
52
+ self._check_interval = config.pin_check_interval_sec
53
+ self._pin_timeout_sec = config.pin_timeout_sec
54
+
55
+ # Register with the global registry
56
+ PeriodicThreadRegistry.get_instance().register(self)
57
+
58
+ # Auto-start the monitor on first instance creation
59
+ self.start_monitoring()
60
+
61
+ @staticmethod
62
+ def GetOrCreate(config: Optional["LMCacheEngineConfig"] = None) -> "PinMonitor":
63
+ """Get or create the singleton instance.
64
+
65
+ Args:
66
+ config: Required for first-time initialization.
67
+ Optional for subsequent calls.
68
+
69
+ Raises:
70
+ ValueError: If config is None when creating the instance
71
+ for the first time.
72
+ """
73
+ if PinMonitor._instance is None:
74
+ with PinMonitor._instance_lock:
75
+ if PinMonitor._instance is None:
76
+ assert config is not None, "config is required"
77
+ PinMonitor._instance = PinMonitor(config)
78
+ return PinMonitor._instance
79
+
80
+ def on_pin(self, memory_obj: "MemoryObj"):
81
+ """Register a pinned memory object for timeout monitoring.
82
+
83
+ Note: The same memory_obj can be pinned multiple times, so this
84
+ function may be called multiple times with the same object.
85
+ Each call updates the register time, effectively resetting the
86
+ timeout countdown.
87
+ """
88
+ obj_id = id(memory_obj)
89
+ with self._objects_lock:
90
+ current_time = time.time()
91
+ self._pinned_objects[obj_id] = (memory_obj, current_time)
92
+ logger.debug(
93
+ "Registered pinned object %s for timeout monitoring at time %.2f",
94
+ obj_id,
95
+ current_time,
96
+ )
97
+
98
+ def on_unpin(self, memory_obj: "MemoryObj"):
99
+ """Unregister a memory object from timeout monitoring."""
100
+ obj_id = id(memory_obj)
101
+ with self._objects_lock:
102
+ if obj_id in self._pinned_objects:
103
+ del self._pinned_objects[obj_id]
104
+ logger.debug(
105
+ "Unregistered pinned object %s from timeout monitoring",
106
+ obj_id,
107
+ )
108
+
109
+ def _check_timeouts(self) -> tuple[int, int, int]:
110
+ """Check all registered pinned objects for timeout.
111
+
112
+ Returns:
113
+ tuple: (pinned_count, timeout_count, force_unpin_success_count)
114
+ """
115
+ current_time = time.time()
116
+ timeout_objects = []
117
+
118
+ with self._objects_lock:
119
+ pinned_count = len(self._pinned_objects)
120
+ for obj_id, (memory_obj, register_time) in list(
121
+ self._pinned_objects.items()
122
+ ):
123
+ # Check if object is still pinned and has exceeded timeout
124
+ if memory_obj.meta.pin_count > 0:
125
+ elapsed_time = current_time - register_time
126
+ if elapsed_time > self._pin_timeout_sec:
127
+ timeout_objects.append((memory_obj, elapsed_time))
128
+
129
+ # Force unpin timeout objects outside the lock to avoid deadlocks
130
+ force_unpin_success_count = 0
131
+ for memory_obj, elapsed_time in timeout_objects:
132
+ try:
133
+ self._force_unpin_timeout_object(memory_obj, elapsed_time)
134
+ force_unpin_success_count += 1
135
+ except Exception as e:
136
+ logger.error(
137
+ "Error forcing unpin for timeout object %s: %s", id(memory_obj), e
138
+ )
139
+ if force_unpin_success_count > 0:
140
+ logger.warning(
141
+ "Force unpinned %d timeout objects in %d pinned_objects "
142
+ "within %d seconds",
143
+ force_unpin_success_count,
144
+ pinned_count,
145
+ self._pin_timeout_sec,
146
+ )
147
+ else:
148
+ logger.debug(
149
+ "PinMonitor check: pinned_objects=%d, timeout_objects=%d, "
150
+ "force_unpin_success=%d",
151
+ pinned_count,
152
+ len(timeout_objects),
153
+ force_unpin_success_count,
154
+ )
155
+
156
+ return pinned_count, len(timeout_objects), force_unpin_success_count
157
+
158
+ def _force_unpin_timeout_object(self, memory_obj: "MemoryObj", elapsed_time: float):
159
+ """Force unpin a timeout object and log the event."""
160
+ # Get current pin_count without holding the lock for unpin calls
161
+ # Use nullcontext if memory_obj doesn't have a lock attribute
162
+ obj_lock = getattr(memory_obj, "lock", None) or nullcontext()
163
+ with obj_lock:
164
+ current_pin_count = memory_obj.meta.pin_count
165
+ if current_pin_count <= 0:
166
+ return
167
+
168
+ logger.warning(
169
+ "Pin timeout detected for MemoryObj %s. "
170
+ "Pin count: %s, Elapsed time: %.2fs. Forcing unpin to 0.",
171
+ memory_obj.meta.address,
172
+ current_pin_count,
173
+ elapsed_time,
174
+ )
175
+
176
+ # Update forced unpin statistics
177
+ LMCStatsMonitor.GetOrCreate().update_forced_unpin_count(1)
178
+
179
+ # Call unpin() while pin_count > 0 to properly release resources
180
+ while memory_obj.meta.pin_count > 0:
181
+ memory_obj.unpin()
182
+
183
+ def _execute(self) -> ThreadRunSummary:
184
+ """
185
+ Execute one pin monitor check cycle.
186
+
187
+ This method is called by the PeriodicThread base class.
188
+
189
+ Returns:
190
+ ThreadRunSummary: Summary of the check cycle
191
+ """
192
+ pinned_count, timeout_count, force_unpin_count = self._check_timeouts()
193
+
194
+ return ThreadRunSummary(
195
+ success=True,
196
+ message=f"Checked {pinned_count} objects, {timeout_count} timeouts, "
197
+ f"{force_unpin_count} force unpinned",
198
+ extra_info={
199
+ "pinned_count": str(pinned_count),
200
+ "timeout_count": str(timeout_count),
201
+ "force_unpin_count": str(force_unpin_count),
202
+ },
203
+ )
204
+
205
+ def start_monitoring(self):
206
+ """Start the background monitoring thread."""
207
+ if self.is_running:
208
+ return
209
+
210
+ # Use base class start method
211
+ self.start()
212
+ logger.info("PinMonitor started")
213
+
214
+ # Setup metrics callback
215
+ prometheus_logger = PrometheusLogger.GetInstanceOrNone()
216
+ if prometheus_logger is not None:
217
+ prometheus_logger.pin_monitor_pinned_objects_count.set_function(
218
+ lambda: len(self._pinned_objects)
219
+ )
220
+
221
+ def stop_monitoring(self):
222
+ """Stop the background monitoring thread."""
223
+ if not self.is_running:
224
+ return
225
+
226
+ # Unregister from the global registry
227
+ PeriodicThreadRegistry.get_instance().unregister(self.name)
228
+
229
+ # Use base class stop method
230
+ self.stop()
231
+ logger.info("PinMonitor stopped")
232
+
233
+ def get_monitored_count(self) -> int:
234
+ """Get the number of currently monitored pinned objects."""
235
+ with self._objects_lock:
236
+ return len(self._pinned_objects)
237
+
238
+ @staticmethod
239
+ def DestroyInstance():
240
+ """Destroy the singleton instance and stop monitoring.
241
+ This is mainly used for testing to ensure clean state between tests.
242
+ """
243
+ with PinMonitor._instance_lock:
244
+ if PinMonitor._instance is not None:
245
+ PinMonitor._instance.stop_monitoring()
246
+ PinMonitor._instance = None
File without changes
@@ -0,0 +1,211 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Standard
3
+ from pathlib import Path
4
+ import atexit
5
+ import os
6
+ import shutil
7
+ import subprocess
8
+ import threading
9
+
10
+ # First Party
11
+ from lmcache.logging import init_logger
12
+
13
+ logger = init_logger(__name__)
14
+
15
+
16
+ class RuntimePluginLauncher:
17
+ def __init__(
18
+ self,
19
+ config,
20
+ role: str | None,
21
+ worker_count: int,
22
+ worker_id: int,
23
+ ):
24
+ self.config = config
25
+ self.role = role
26
+ self.worker_count = worker_count
27
+ self.worker_id = worker_id
28
+ self.plugin_processes: list[subprocess.Popen] = []
29
+ # Register cleanup handler
30
+ atexit.register(self.stop_plugins)
31
+
32
+ def launch_plugins(self):
33
+ """Launch all configured plugins"""
34
+ if not self.config.runtime_plugin_locations:
35
+ return
36
+
37
+ for loc in self.config.runtime_plugin_locations:
38
+ self._launch_plugins(loc)
39
+
40
+ def _launch_plugins(self, loc: str):
41
+ """Launch plugins from specified location"""
42
+ path = Path(loc)
43
+ if not path.exists():
44
+ logger.warning(f"Runtime plugin location {loc} does not exist")
45
+ return
46
+
47
+ files = []
48
+ if path.is_file():
49
+ files = [path]
50
+ elif path.is_dir():
51
+ # Recursively find all .py and .sh files
52
+ for ext in ["*.py", "*.sh"]:
53
+ files.extend(path.rglob(ext))
54
+
55
+ for file in files:
56
+ self._launch_plugin(file)
57
+
58
+ def _should_skip_plugin(self, file: Path, parts: list[str]) -> bool:
59
+ """Determine if plugin should be skipped based on role/worker ID.
60
+
61
+ The naming convention is ROLE_WORKERID_NAME (e.g. server_0_foo.py).
62
+ When role is None (MP mode), this convention does not apply,
63
+ so both role and worker ID filtering are skipped entirely.
64
+ """
65
+ if len(parts) < 2:
66
+ return False
67
+
68
+ # When role is None, skip all role/worker-based filtering
69
+ # (e.g. MP mode has no role concept)
70
+ if self.role is None:
71
+ return False
72
+
73
+ plugin_role = parts[0].upper()
74
+ if plugin_role != "ALL" and plugin_role != self.role.upper():
75
+ logger.info(
76
+ "Skipping %s: requires role %s",
77
+ file,
78
+ plugin_role,
79
+ )
80
+ return True
81
+
82
+ # Check worker ID match (parts[1] in ROLE_WORKERID_NAME)
83
+ if len(parts) > 2 and parts[1].isdigit():
84
+ plugin_worker_id = int(parts[1])
85
+ if plugin_worker_id != self.worker_id:
86
+ logger.info(
87
+ "worker %d is skipping plugin %s, which is only for worker ID %d",
88
+ self.worker_id,
89
+ file,
90
+ plugin_worker_id,
91
+ )
92
+ return True
93
+
94
+ return False
95
+
96
+ def _launch_plugin(self, file: Path):
97
+ """Launch a plugin"""
98
+ try:
99
+ filename = file.stem.lower()
100
+ parts = filename.split("_")
101
+
102
+ if self._should_skip_plugin(file, parts):
103
+ return
104
+
105
+ # Get interpreter from first line (shebang)
106
+ interpreter = self._get_interpreter(file)
107
+
108
+ # Pass role and config as environment variables
109
+ env = os.environ.copy()
110
+ role_str = self.role or ""
111
+ env["LMCACHE_RUNTIME_PLUGIN_ROLE"] = role_str
112
+ env["LMCACHE_RUNTIME_PLUGIN_CONFIG"] = self.config.to_json()
113
+ env["LMCACHE_RUNTIME_PLUGIN_WORKER_COUNT"] = str(self.worker_count)
114
+ env["LMCACHE_RUNTIME_PLUGIN_WORKER_ID"] = str(self.worker_id)
115
+
116
+ # TODO: For backwards compatibility, remove when applicable
117
+ env["LMCACHE_PLUGIN_ROLE"] = role_str
118
+ env["LMCACHE_PLUGIN_CONFIG"] = self.config.to_json()
119
+ env["LMCACHE_PLUGIN_WORKER_COUNT"] = str(self.worker_count)
120
+ env["LMCACHE_PLUGIN_WORKER_ID"] = str(self.worker_id)
121
+
122
+ # Force line-buffered stdout for Python sub-processes
123
+ # so that output is captured in real-time rather than
124
+ # being held in the block buffer until exit.
125
+ env["PYTHONUNBUFFERED"] = "1"
126
+
127
+ proc = subprocess.Popen(
128
+ [interpreter, str(file)],
129
+ env=env,
130
+ stdout=subprocess.PIPE,
131
+ stderr=subprocess.STDOUT,
132
+ text=True,
133
+ )
134
+ self.plugin_processes.append(proc)
135
+ logger.info(f"Launched runtime plugin: {file} with {interpreter}")
136
+
137
+ # Start thread to capture output continuously
138
+ threading.Thread(
139
+ target=self._capture_plugin_output, args=(proc, str(file)), daemon=True
140
+ ).start()
141
+ except Exception as e:
142
+ logger.error(f"Failed to launch plugin {file}: {e}")
143
+
144
+ def _get_interpreter(self, file: Path) -> str:
145
+ """Get interpreter from first line comment"""
146
+ interpreters = []
147
+ try:
148
+ with open(file, "r", encoding="utf-8") as f:
149
+ first_line = f.readline().strip()
150
+ if first_line.startswith("#!"):
151
+ # Extract interpreter
152
+ interpreter_str = first_line[2:].strip()
153
+ interpreters.append(interpreter_str)
154
+ except Exception as e:
155
+ logger.error(
156
+ f"Error reading interpreter from runtime plugin file {file} - "
157
+ f"using default interpreters: {e}"
158
+ )
159
+ pass
160
+
161
+ # Fallback to default interpreters
162
+ if file.suffix == ".py":
163
+ interpreters.append("python")
164
+ interpreters.append("python3")
165
+ elif file.suffix == ".sh":
166
+ interpreters.append("bash")
167
+ else:
168
+ raise ValueError(f"Plugin type {file.suffix} not supported ")
169
+
170
+ # Try each interpreter until we find one that exists
171
+ for interpreter in interpreters:
172
+ interpreter = interpreter.strip()
173
+ resolved_interpreter = shutil.which(interpreter)
174
+ if resolved_interpreter:
175
+ return resolved_interpreter
176
+
177
+ raise ValueError(f"No valid interpreter found for {file} from {interpreters}")
178
+
179
+ def _capture_plugin_output(self, proc: subprocess.Popen, plugin_name: str):
180
+ """Continuously capture and log plugin output"""
181
+ try:
182
+ assert proc.stdout is not None, (
183
+ "The runtime plugin subprocess does not have stdout"
184
+ )
185
+ while True:
186
+ line = proc.stdout.readline()
187
+ if not line:
188
+ break
189
+ logger.info(f"[{plugin_name}] {line.strip()}")
190
+
191
+ proc.wait()
192
+ logger.info(
193
+ f"Runtime plugin {plugin_name} exited with code {proc.returncode}"
194
+ )
195
+ except Exception as e:
196
+ logger.error(f"Error capturing output for {plugin_name}: {e}")
197
+
198
+ def stop_plugins(self):
199
+ """Terminate all plugin processes.
200
+
201
+ Note: This method may be called via atexit during interpreter shutdown,
202
+ when the logging system may already be closed. We avoid using logger
203
+ here to prevent "I/O operation on closed file" errors.
204
+ """
205
+ for proc in self.plugin_processes:
206
+ try:
207
+ if proc.poll() is None:
208
+ proc.terminate()
209
+ except Exception:
210
+ # Silently ignore errors during shutdown
211
+ pass