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,19 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Standard
3
+ from typing import Optional
4
+
5
+ # Third Party
6
+ import msgspec
7
+
8
+
9
+ class LMCacheModelRequest(
10
+ msgspec.Struct,
11
+ array_like=True, # type: ignore[call-arg]
12
+ omit_defaults=True,
13
+ ): # type: ignore[call-arg]
14
+ """
15
+ User-provided information to control the cache behavior.
16
+ """
17
+
18
+ store_cache: bool = True # Whether to store the cache
19
+ ttl: Optional[float] = None # Time to live
@@ -0,0 +1,74 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """Check mode registry implementation"""
3
+
4
+ # Standard
5
+ from typing import Callable, Dict, Optional
6
+ import importlib
7
+ import inspect
8
+ import os
9
+
10
+ # First Party
11
+ from lmcache.logging import init_logger
12
+
13
+ logger = init_logger(__name__)
14
+
15
+
16
+ class CheckModeRegistry:
17
+ """Registry for dynamically loaded check modes"""
18
+
19
+ def __init__(self):
20
+ self.modes: Dict[str, Callable] = {}
21
+ self.loaded = False
22
+
23
+ def register(self, name: str, func: Callable):
24
+ """Register a check mode function"""
25
+ if name in self.modes:
26
+ raise ValueError(f"Check mode '{name}' already registered")
27
+ self.modes[name] = func
28
+
29
+ def load_modes(self):
30
+ """Dynamically load all check mode modules"""
31
+ if self.loaded:
32
+ return
33
+
34
+ # Get current package
35
+ current_dir = os.path.dirname(__file__)
36
+
37
+ # Find all modules with check_mode_ prefix
38
+ for filename in os.listdir(current_dir):
39
+ if filename.startswith("check_mode_") and filename.endswith(".py"):
40
+ module_name = filename[:-3] # Remove .py
41
+ try:
42
+ module = importlib.import_module(
43
+ f".{module_name}", package=__package__
44
+ )
45
+ # Find and register mode functions
46
+ for name, obj in inspect.getmembers(module):
47
+ if inspect.isfunction(obj) and hasattr(obj, "is_check_mode"):
48
+ self.register(obj.mode_name, obj)
49
+ except ImportError as e:
50
+ logger.error(f"Failed to load check mode module {module_name}: {e}")
51
+
52
+ self.loaded = True
53
+ logger.info(f"Loaded {len(self.modes)} check modes")
54
+
55
+ def get_mode(self, name: str) -> Optional[Callable]:
56
+ """Get registered mode function. Returns None if the mode is not found."""
57
+ if not self.loaded:
58
+ self.load_modes()
59
+ return self.modes.get(name)
60
+
61
+
62
+ def check_mode(name: str):
63
+ """Decorator to mark functions as check modes"""
64
+
65
+ def decorator(func):
66
+ func.is_check_mode = True
67
+ func.mode_name = name
68
+ return func
69
+
70
+ return decorator
71
+
72
+
73
+ # Global registry instance
74
+ registry = CheckModeRegistry()
@@ -0,0 +1,86 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """Generate mode implementation for key generation"""
3
+
4
+ # Third Party
5
+ import tqdm
6
+
7
+ # First Party
8
+ from lmcache.v1.check import check_mode
9
+ from lmcache.v1.check.utils import (
10
+ _get_default_metadata,
11
+ create_memory_objects_batch,
12
+ create_storage_manager_with_config,
13
+ create_test_key,
14
+ find_remote_backend,
15
+ flow_control_check,
16
+ wait_put_tasks_complete,
17
+ )
18
+
19
+
20
+ @check_mode("gen")
21
+ async def run_gen_mode(
22
+ model: str, num_keys: int, concurrency: int, offset: int = 0, **kwargs
23
+ ):
24
+ """Run key generation mode"""
25
+ # Create storage manager using common function
26
+ storage_manager = create_storage_manager_with_config(model)
27
+ metadata = _get_default_metadata(model)
28
+
29
+ try:
30
+ print("Generate: Passed - Created storage manager with valid config")
31
+
32
+ # Find remote backend for flow control
33
+ remote_backend = find_remote_backend(storage_manager)
34
+
35
+ # Create limited number of memory objects for reuse (memory efficiency)
36
+ batch_size = min(concurrency, 100) # Limit to 100 for memory efficiency
37
+ memory_objs = create_memory_objects_batch(storage_manager, metadata, batch_size)
38
+
39
+ if not memory_objs:
40
+ print("Generate: Failed - Could not allocate any memory objects")
41
+ return
42
+
43
+ # Create progress bar
44
+ progress_bar = tqdm.tqdm(
45
+ total=num_keys, desc="Generating keys", unit="key", unit_scale=True
46
+ )
47
+ sleep_count = 1.0
48
+ # Process keys in batches of concurrency size
49
+ for batch_start in range(0, num_keys, concurrency):
50
+ batch_end = min(batch_start + concurrency, num_keys)
51
+ batch_keys = []
52
+ batch_memory_objs = []
53
+
54
+ # Create keys and reuse memory objects for this batch
55
+ for i in range(batch_start, batch_end):
56
+ key = create_test_key(model, f"gen_{offset + i}")
57
+ # Reuse memory objects in round-robin fashion
58
+ memory_obj = memory_objs[i % len(memory_objs)]
59
+ batch_keys.append(key)
60
+ batch_memory_objs.append(memory_obj)
61
+ memory_obj.ref_count_up()
62
+
63
+ # Flow control: check if remote backend has too many pending tasks
64
+ sleep_count = await flow_control_check(
65
+ remote_backend, concurrency, sleep_count
66
+ )
67
+
68
+ # Use batched_put to store the batch of memory objects
69
+ storage_manager.batched_put(batch_keys, batch_memory_objs)
70
+
71
+ # Update progress bar
72
+ progress_bar.update(len(batch_keys))
73
+
74
+ progress_bar.close()
75
+ print(f"Generate: Successfully generated {num_keys} keys")
76
+
77
+ # Wait for remote backend put_tasks to complete
78
+ wait_put_tasks_complete(find_remote_backend(storage_manager))
79
+
80
+ except Exception as e:
81
+ print(
82
+ f"Generate: Failed - Error creating storage manager with valid config: {e}"
83
+ )
84
+ finally:
85
+ if storage_manager:
86
+ storage_manager.close()
@@ -0,0 +1,284 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """Test mode implementation for MP mode L2 adapter basic checks"""
3
+
4
+ # Standard
5
+ import argparse
6
+ import os
7
+ import select
8
+ import time
9
+
10
+ # Third Party
11
+ import torch
12
+
13
+ # First Party
14
+ from lmcache.v1.check import check_mode
15
+ from lmcache.v1.check.utils import (
16
+ DEFAULT_KV_DTYPE_STR,
17
+ DEFAULT_OBJ_SIZE,
18
+ parse_kv_dtype,
19
+ print_performance_results,
20
+ )
21
+ from lmcache.v1.distributed.api import ObjectKey
22
+ from lmcache.v1.distributed.l2_adapters import create_l2_adapter
23
+ from lmcache.v1.distributed.l2_adapters.config import (
24
+ parse_args_to_l2_adapters_config,
25
+ )
26
+ from lmcache.v1.memory_management import (
27
+ MemoryFormat,
28
+ MemoryObjMetadata,
29
+ TensorMemoryObj,
30
+ )
31
+
32
+ _POLL_TIMEOUT_MS = 100000
33
+
34
+
35
+ def _create_object_key(model: str, key_id: str) -> ObjectKey:
36
+ """Create a test ObjectKey."""
37
+ return ObjectKey(
38
+ chunk_hash=ObjectKey.IntHash2Bytes(hash(key_id) & 0xFFFFFFFF),
39
+ model_name=model,
40
+ kv_rank=0,
41
+ )
42
+
43
+
44
+ def _create_memory_obj(
45
+ fill_value: float = 0.0,
46
+ obj_size: int = DEFAULT_OBJ_SIZE,
47
+ dtype: torch.dtype = torch.float32,
48
+ ) -> TensorMemoryObj:
49
+ """Create a test TensorMemoryObj."""
50
+ raw_data = torch.empty(obj_size, dtype=dtype)
51
+ raw_data.fill_(fill_value)
52
+ metadata = MemoryObjMetadata(
53
+ shape=torch.Size([obj_size]),
54
+ dtype=dtype,
55
+ address=0,
56
+ phy_size=obj_size * raw_data.element_size(),
57
+ fmt=MemoryFormat.KV_2LTD,
58
+ ref_count=1,
59
+ )
60
+ return TensorMemoryObj(raw_data, metadata, parent_allocator=None)
61
+
62
+
63
+ def _wait_event_fd(efd: int, timeout_ms: int = _POLL_TIMEOUT_MS) -> bool:
64
+ """Wait for an eventfd to be signaled."""
65
+ poll = select.poll()
66
+ poll.register(efd, select.POLLIN)
67
+ events = poll.poll(timeout_ms)
68
+ if events:
69
+ try:
70
+ os.eventfd_read(efd)
71
+ except BlockingIOError:
72
+ pass
73
+ return True
74
+ return False
75
+
76
+
77
+ def _run_store_phase(adapter, keys, objects):
78
+ """Run store phase and return (stats, success)."""
79
+ efd = adapter.get_store_event_fd()
80
+ start = time.perf_counter()
81
+ task_id = adapter.submit_store_task(keys, objects)
82
+ if not _wait_event_fd(efd):
83
+ print(" Store: timed out waiting for eventfd")
84
+ return None, False
85
+ completed = adapter.pop_completed_store_tasks()
86
+ elapsed_ms = (time.perf_counter() - start) * 1000
87
+ ok = completed.get(task_id, False)
88
+ return elapsed_ms, ok
89
+
90
+
91
+ def _run_lookup_phase(adapter, keys):
92
+ """Run lookup phase and return (stats, bitmap)."""
93
+ efd = adapter.get_lookup_and_lock_event_fd()
94
+ start = time.perf_counter()
95
+ task_id = adapter.submit_lookup_and_lock_task(keys)
96
+ if not _wait_event_fd(efd):
97
+ print(" Lookup: timed out waiting for eventfd")
98
+ return None, None
99
+ bitmap = adapter.query_lookup_and_lock_result(task_id)
100
+ elapsed_ms = (time.perf_counter() - start) * 1000
101
+ return elapsed_ms, bitmap
102
+
103
+
104
+ def _run_load_phase(adapter, keys, buffers):
105
+ """Run load phase and return (stats, bitmap)."""
106
+ efd = adapter.get_load_event_fd()
107
+ start = time.perf_counter()
108
+ task_id = adapter.submit_load_task(keys, buffers)
109
+ if not _wait_event_fd(efd):
110
+ print(" Load: timed out waiting for eventfd")
111
+ return None, None
112
+ bitmap = adapter.query_load_result(task_id)
113
+ elapsed_ms = (time.perf_counter() - start) * 1000
114
+ return elapsed_ms, bitmap
115
+
116
+
117
+ @check_mode("test_l2_adapter")
118
+ async def run_test_mode(model: str, **kwargs):
119
+ """Run L2 adapter test mode.
120
+
121
+ Requires ``l2_adapter`` in *kwargs* (list of JSON
122
+ strings from ``--l2-adapter``).
123
+ """
124
+ l2_adapter_raw = kwargs.get("l2_adapter")
125
+ if not l2_adapter_raw:
126
+ print("Error: --l2-adapter is required for test_l2_adapter mode")
127
+ return
128
+
129
+ obj_size = kwargs.get("obj_size") or DEFAULT_OBJ_SIZE
130
+ kv_dtype_str = kwargs.get("kv_dtype") or DEFAULT_KV_DTYPE_STR
131
+ kv_dtype = parse_kv_dtype(kv_dtype_str)
132
+ if kv_dtype is None:
133
+ print("Error: unsupported --kv-dtype '%s'" % kv_dtype_str)
134
+ return
135
+
136
+ # Build adapter config via the standard parser
137
+ ns = argparse.Namespace(l2_adapter=l2_adapter_raw)
138
+ l2_cfg = parse_args_to_l2_adapters_config(ns)
139
+ if not l2_cfg.adapters:
140
+ print("Error: no L2 adapter configs parsed")
141
+ return
142
+
143
+ num_tests = kwargs.get("num_keys", 5)
144
+ settle_time = kwargs.get("settle_time", 0.0)
145
+
146
+ for idx, adapter_cfg in enumerate(l2_cfg.adapters):
147
+ adapter = create_l2_adapter(adapter_cfg)
148
+ print("=== Testing L2 adapter #%d (%s) ===" % (idx, type(adapter).__name__))
149
+
150
+ try:
151
+ _test_single_adapter(
152
+ adapter,
153
+ model,
154
+ num_tests,
155
+ obj_size=obj_size,
156
+ kv_dtype=kv_dtype,
157
+ settle_time=settle_time,
158
+ )
159
+ except Exception as e:
160
+ print(" Test Failed - Error: %s" % e)
161
+ finally:
162
+ adapter.close()
163
+
164
+
165
+ def _test_single_adapter(
166
+ adapter,
167
+ model,
168
+ num_tests,
169
+ obj_size=DEFAULT_OBJ_SIZE,
170
+ kv_dtype=torch.float32,
171
+ settle_time=0.0,
172
+ ):
173
+ """Run all test phases against one adapter."""
174
+ # -- Prepare test data -----------------------------------
175
+ exist_keys = [_create_object_key(model, "exist_%d" % i) for i in range(num_tests)]
176
+ non_exist_keys = [
177
+ _create_object_key(model, "nonexist_%d" % i) for i in range(num_tests)
178
+ ]
179
+ store_objs = [
180
+ _create_memory_obj(float(i + 1), obj_size, kv_dtype) for i in range(num_tests)
181
+ ]
182
+
183
+ # -- Phase 1: lookup non-existing keys -------------------
184
+ print("Phase 1: Lookup non-existing keys...")
185
+ lk_absent_ms, lk_bitmap = _run_lookup_phase(adapter, non_exist_keys)
186
+ if lk_bitmap is None:
187
+ print(" FAIL: lookup returned None bitmap")
188
+ ne_pass = 0
189
+ else:
190
+ ne_pass = sum(1 for i in range(num_tests) if not lk_bitmap.test(i))
191
+ print(" Validation: %d/%d correctly absent" % (ne_pass, num_tests))
192
+ # Unlock the looked-up keys (contract)
193
+ adapter.submit_unlock(non_exist_keys)
194
+
195
+ # -- Phase 2: store existing keys ------------------------
196
+ print("Phase 2: Store operations (batch of %d)..." % num_tests)
197
+ st_ms, st_ok = _run_store_phase(adapter, exist_keys, store_objs)
198
+ store_pass = num_tests if st_ok else 0
199
+ print(" Batch store %s (%.2fms)" % ("OK" if st_ok else "FAIL", st_ms or 0))
200
+
201
+ if settle_time > 0:
202
+ print(" Waiting %.1fs for data to settle..." % settle_time)
203
+ time.sleep(settle_time)
204
+
205
+ # -- Phase 3: lookup existing keys -----------------------
206
+ print("Phase 3: Lookup existing keys...")
207
+ lk_exist_ms, lk_bitmap = _run_lookup_phase(adapter, exist_keys)
208
+ if lk_bitmap is None:
209
+ print(" FAIL: lookup returned None bitmap")
210
+ exist_pass = 0
211
+ else:
212
+ exist_pass = sum(1 for i in range(num_tests) if lk_bitmap.test(i))
213
+ print(" Validation: %d/%d found" % (exist_pass, num_tests))
214
+
215
+ # -- Phase 4: load existing keys -------------------------
216
+ print("Phase 4: Load operations...")
217
+ load_buffers = [
218
+ _create_memory_obj(0.0, obj_size, kv_dtype) for _ in range(num_tests)
219
+ ]
220
+ ld_ms, ld_bitmap = _run_load_phase(adapter, exist_keys, load_buffers)
221
+ load_pass = 0
222
+ content_pass = 0
223
+ if ld_bitmap is not None:
224
+ for i in range(num_tests):
225
+ if ld_bitmap.test(i):
226
+ load_pass += 1
227
+ if torch.equal(
228
+ load_buffers[i].tensor,
229
+ store_objs[i].tensor,
230
+ ):
231
+ content_pass += 1
232
+ else:
233
+ print(" Key %d: data mismatch" % i)
234
+ print(" Validation (loaded): %d/%d" % (load_pass, num_tests))
235
+ print(" Validation (content): %d/%d" % (content_pass, num_tests))
236
+
237
+ # Unlock after load
238
+ adapter.submit_unlock(exist_keys)
239
+
240
+ # -- Summary ---------------------------------------------
241
+ total_bytes = obj_size * store_objs[0].tensor.element_size() * num_tests
242
+ stats_data = [
243
+ (
244
+ "LOOKUP (absent)",
245
+ {
246
+ "avg": lk_absent_ms or 0,
247
+ "max": lk_absent_ms or 0,
248
+ "min": lk_absent_ms or 0,
249
+ },
250
+ [False] * num_tests,
251
+ ne_pass,
252
+ ),
253
+ (
254
+ "STORE",
255
+ {
256
+ "avg": st_ms or 0,
257
+ "max": st_ms or 0,
258
+ "min": st_ms or 0,
259
+ },
260
+ [True] * store_pass + [False] * (num_tests - store_pass),
261
+ store_pass,
262
+ ),
263
+ (
264
+ "LOOKUP (exist)",
265
+ {
266
+ "avg": lk_exist_ms or 0,
267
+ "max": lk_exist_ms or 0,
268
+ "min": lk_exist_ms or 0,
269
+ },
270
+ [True] * exist_pass + [False] * (num_tests - exist_pass),
271
+ exist_pass,
272
+ ),
273
+ (
274
+ "LOAD",
275
+ {
276
+ "avg": ld_ms or 0,
277
+ "max": ld_ms or 0,
278
+ "min": ld_ms or 0,
279
+ },
280
+ [True] * content_pass + [False] * (num_tests - content_pass),
281
+ content_pass,
282
+ ),
283
+ ]
284
+ print_performance_results(stats_data, obj_bytes=total_bytes)
@@ -0,0 +1,155 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ """Test mode implementation for basic checks"""
3
+
4
+ # Standard
5
+ import asyncio
6
+
7
+ # First Party
8
+ from lmcache.integration.vllm.utils import lmcache_get_or_create_config
9
+ from lmcache.v1.check import check_mode
10
+
11
+ # Import shared utilities
12
+ from lmcache.v1.check.utils import (
13
+ DEFAULT_KV_DTYPE_STR,
14
+ EventLoopManager,
15
+ _get_default_metadata,
16
+ create_test_key,
17
+ parse_kv_dtype,
18
+ run_common_test_framework,
19
+ validate_get_results,
20
+ )
21
+ from lmcache.v1.memory_management import MemoryObj
22
+
23
+ # Import from lmcache with absolute paths
24
+ from lmcache.v1.storage_backend import RemoteBackend
25
+ from lmcache.v1.storage_backend.connector import InstrumentedRemoteConnector
26
+ from lmcache.v1.storage_backend.local_cpu_backend import LocalCPUBackend
27
+
28
+
29
+ async def async_contains_backend(backend, key):
30
+ """Async wrapper for backend contains method"""
31
+ return backend.contains(key)
32
+
33
+
34
+ async def async_get_backend(backend, key):
35
+ """Async wrapper for backend get_blocking method"""
36
+ return backend.get_blocking(key)
37
+
38
+
39
+ async def async_submit_put_backend(backend, key, memory_obj):
40
+ """Async wrapper for backend submit_put_task"""
41
+ future = backend.submit_put_task(key, memory_obj)
42
+ # Wait for the future to complete with timeout
43
+ try:
44
+ await asyncio.wait_for(asyncio.wrap_future(future), timeout=10.0)
45
+ return True
46
+ except asyncio.TimeoutError:
47
+ print(f"Put task timed out for key: {key}")
48
+ return False
49
+
50
+
51
+ def create_test_memory_obj(
52
+ backend: RemoteBackend, local_cpu_backend: LocalCPUBackend
53
+ ) -> MemoryObj:
54
+ """Create a test MemoryObj for testing."""
55
+ if backend.connection is None:
56
+ raise ValueError("Backend connection is None")
57
+
58
+ if isinstance(backend.connection, InstrumentedRemoteConnector):
59
+ connector = backend.connection.getWrappedConnector()
60
+ else:
61
+ connector = backend.connection
62
+
63
+ return local_cpu_backend.allocate(
64
+ connector.meta_shapes, connector.meta_dtypes, connector.meta_fmt
65
+ )
66
+
67
+
68
+ def create_test_data_for_backend(
69
+ backend,
70
+ local_cpu_backend,
71
+ model,
72
+ num_tests,
73
+ kv_dtype=None,
74
+ ):
75
+ """Create test data for backend based tests"""
76
+ # Group 1: Non-existing keys
77
+ kw = {} if kv_dtype is None else {"kv_dtype": kv_dtype}
78
+ non_exist_keys = [
79
+ create_test_key(model, f"non_exist_{i}", **kw) for i in range(num_tests)
80
+ ]
81
+
82
+ # Group 2: Existing keys
83
+ exist_keys = [create_test_key(model, f"exist_{i}", **kw) for i in range(num_tests)]
84
+ exist_memories = [
85
+ create_test_memory_obj(backend, local_cpu_backend) for _ in range(num_tests)
86
+ ]
87
+
88
+ return non_exist_keys, exist_keys, exist_memories, num_tests
89
+
90
+
91
+ @check_mode("test_remote")
92
+ async def run_test_mode(model: str, **kwargs):
93
+ """Run connector test mode"""
94
+ kv_dtype_str = kwargs.get("kv_dtype") or DEFAULT_KV_DTYPE_STR
95
+ kv_dtype = parse_kv_dtype(kv_dtype_str)
96
+ if kv_dtype is None:
97
+ print("Error: unsupported --kv-dtype '%s'" % kv_dtype_str)
98
+ return
99
+
100
+ obj_size = kwargs.get("obj_size")
101
+
102
+ config = lmcache_get_or_create_config()
103
+ metadata = _get_default_metadata(model, kv_dtype=kv_dtype, obj_size=obj_size)
104
+
105
+ # Create and start event loop manager
106
+ loop_manager = EventLoopManager()
107
+ loop_manager.start()
108
+
109
+ local_cpu_backend = LocalCPUBackend(
110
+ config=config, metadata=metadata, dst_device="cpu"
111
+ )
112
+
113
+ backend = RemoteBackend(
114
+ config=config,
115
+ metadata=metadata,
116
+ loop=loop_manager.get_loop(),
117
+ local_cpu_backend=local_cpu_backend,
118
+ dst_device="cpu",
119
+ )
120
+
121
+ try:
122
+ # Create test context for the common framework
123
+ test_context = {
124
+ "create_test_data_func": create_test_data_for_backend,
125
+ "async_contains_func": async_contains_backend,
126
+ "async_put_func": async_submit_put_backend,
127
+ "async_get_func": async_get_backend,
128
+ "validate_get_func": validate_get_results,
129
+ "test_object": backend,
130
+ "extra_args": [
131
+ local_cpu_backend,
132
+ ],
133
+ "kv_dtype": kv_dtype,
134
+ "obj_size": obj_size,
135
+ }
136
+
137
+ # Run the common test framework
138
+ num_tests = kwargs.get("num_keys", 5)
139
+ settle_time = kwargs.get("settle_time", 0.0)
140
+ await run_common_test_framework(
141
+ test_context, model, num_tests=num_tests, settle_time=settle_time
142
+ )
143
+
144
+ except Exception as e:
145
+ print(f"Test Failed - Error: {e}")
146
+ finally:
147
+ # Clean up
148
+ try:
149
+ if backend:
150
+ backend.close()
151
+ except Exception as e:
152
+ print(f"Error closing backend: {e}")
153
+
154
+ # Stop the event loop
155
+ loop_manager.stop()