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.
- lmcache/__init__.py +84 -0
- lmcache/_version.py +24 -0
- lmcache/cli/__init__.py +1 -0
- lmcache/cli/commands/__init__.py +34 -0
- lmcache/cli/commands/base.py +157 -0
- lmcache/cli/commands/bench/__init__.py +557 -0
- lmcache/cli/commands/bench/engine_bench/__init__.py +1 -0
- lmcache/cli/commands/bench/engine_bench/config.py +245 -0
- lmcache/cli/commands/bench/engine_bench/interactive/__init__.py +274 -0
- lmcache/cli/commands/bench/engine_bench/interactive/config.json +10 -0
- lmcache/cli/commands/bench/engine_bench/interactive/schema.py +352 -0
- lmcache/cli/commands/bench/engine_bench/interactive/state.py +327 -0
- lmcache/cli/commands/bench/engine_bench/interactive/terminal.py +291 -0
- lmcache/cli/commands/bench/engine_bench/progress.py +145 -0
- lmcache/cli/commands/bench/engine_bench/request_sender.py +232 -0
- lmcache/cli/commands/bench/engine_bench/stats.py +275 -0
- lmcache/cli/commands/bench/engine_bench/workloads/__init__.py +153 -0
- lmcache/cli/commands/bench/engine_bench/workloads/base.py +122 -0
- lmcache/cli/commands/bench/engine_bench/workloads/long_doc_permutator.py +435 -0
- lmcache/cli/commands/bench/engine_bench/workloads/long_doc_qa.py +281 -0
- lmcache/cli/commands/bench/engine_bench/workloads/multi_round_chat.py +337 -0
- lmcache/cli/commands/bench/engine_bench/workloads/random_prefill.py +178 -0
- lmcache/cli/commands/describe.py +310 -0
- lmcache/cli/commands/kvcache.py +133 -0
- lmcache/cli/commands/mock.py +75 -0
- lmcache/cli/commands/ping.py +113 -0
- lmcache/cli/commands/query/__init__.py +155 -0
- lmcache/cli/commands/query/prompt.py +134 -0
- lmcache/cli/commands/query/request.py +357 -0
- lmcache/cli/commands/server.py +99 -0
- lmcache/cli/commands/tool/__init__.py +63 -0
- lmcache/cli/commands/tool/cache_simulator.py +113 -0
- lmcache/cli/commands/trace/__init__.py +505 -0
- lmcache/cli/commands/trace/dispatch.py +249 -0
- lmcache/cli/commands/trace/driver.py +372 -0
- lmcache/cli/commands/trace/stats.py +289 -0
- lmcache/cli/documents/lmcache.txt +11 -0
- lmcache/cli/main.py +42 -0
- lmcache/cli/metrics/__init__.py +29 -0
- lmcache/cli/metrics/formatter.py +171 -0
- lmcache/cli/metrics/handler.py +94 -0
- lmcache/cli/metrics/metrics.py +161 -0
- lmcache/cli/metrics/section.py +77 -0
- lmcache/connections.py +173 -0
- lmcache/integration/__init__.py +2 -0
- lmcache/integration/base_service_factory.py +165 -0
- lmcache/integration/request_telemetry/__init__.py +1 -0
- lmcache/integration/request_telemetry/base.py +51 -0
- lmcache/integration/request_telemetry/factory.py +113 -0
- lmcache/integration/request_telemetry/fastapi.py +109 -0
- lmcache/integration/request_telemetry/noop.py +35 -0
- lmcache/integration/sglang/__init__.py +2 -0
- lmcache/integration/sglang/sglang_adapter.py +326 -0
- lmcache/integration/sglang/utils.py +39 -0
- lmcache/integration/vllm/__init__.py +1 -0
- lmcache/integration/vllm/lmcache_connector_v1.py +213 -0
- lmcache/integration/vllm/lmcache_connector_v1_085.py +150 -0
- lmcache/integration/vllm/lmcache_mp_connector_0180.py +1072 -0
- lmcache/integration/vllm/tests/test_mm_hash_utils.py +112 -0
- lmcache/integration/vllm/utils.py +433 -0
- lmcache/integration/vllm/vllm_multi_process_adapter.py +1090 -0
- lmcache/integration/vllm/vllm_service_factory.py +339 -0
- lmcache/integration/vllm/vllm_v1_adapter.py +1713 -0
- lmcache/logging.py +107 -0
- lmcache/native_storage_ops.pyi +230 -0
- lmcache/non_cuda_equivalents.py +1424 -0
- lmcache/observability.py +1958 -0
- lmcache/storage_backend/serde/__init__.py +1 -0
- lmcache/storage_backend/serde/cachegen_basics.py +210 -0
- lmcache/storage_backend/serde/cachegen_decoder.py +207 -0
- lmcache/storage_backend/serde/cachegen_encoder.py +394 -0
- lmcache/storage_backend/serde/serde.py +75 -0
- lmcache/tools/__init__.py +1 -0
- lmcache/tools/cache_simulator/README.md +392 -0
- lmcache/tools/cache_simulator/__init__.py +1 -0
- lmcache/tools/cache_simulator/docs/simulate_example.png +0 -0
- lmcache/tools/cache_simulator/docs/sweep_example.png +0 -0
- lmcache/tools/cache_simulator/gen_bench_dataset.py +360 -0
- lmcache/tools/cache_simulator/lru_cache.py +124 -0
- lmcache/tools/cache_simulator/plot_hit_rate.py +231 -0
- lmcache/tools/cache_simulator/simulator.py +795 -0
- lmcache/tools/controller_benchmark/README.md +161 -0
- lmcache/tools/controller_benchmark/__init__.py +1 -0
- lmcache/tools/controller_benchmark/__main__.py +331 -0
- lmcache/tools/controller_benchmark/benchmark.py +660 -0
- lmcache/tools/controller_benchmark/config.py +44 -0
- lmcache/tools/controller_benchmark/constants.py +10 -0
- lmcache/tools/controller_benchmark/handlers/__init__.py +46 -0
- lmcache/tools/controller_benchmark/handlers/admit.py +52 -0
- lmcache/tools/controller_benchmark/handlers/base.py +47 -0
- lmcache/tools/controller_benchmark/handlers/deregister.py +49 -0
- lmcache/tools/controller_benchmark/handlers/evict.py +52 -0
- lmcache/tools/controller_benchmark/handlers/heartbeat.py +56 -0
- lmcache/tools/controller_benchmark/handlers/p2p_lookup.py +47 -0
- lmcache/tools/controller_benchmark/handlers/register.py +56 -0
- lmcache/tools/mp_status_viewer/__init__.py +1 -0
- lmcache/tools/mp_status_viewer/__main__.py +95 -0
- lmcache/usage_context.py +417 -0
- lmcache/utils.py +665 -0
- lmcache/v1/__init__.py +2 -0
- lmcache/v1/api_server/__init__.py +2 -0
- lmcache/v1/api_server/__main__.py +537 -0
- lmcache/v1/basic_check.py +112 -0
- lmcache/v1/cache_controller/__init__.py +9 -0
- lmcache/v1/cache_controller/commands/__init__.py +15 -0
- lmcache/v1/cache_controller/commands/base.py +35 -0
- lmcache/v1/cache_controller/commands/full_sync.py +49 -0
- lmcache/v1/cache_controller/config.py +176 -0
- lmcache/v1/cache_controller/controller_manager.py +535 -0
- lmcache/v1/cache_controller/controllers/__init__.py +11 -0
- lmcache/v1/cache_controller/controllers/full_sync_tracker.py +473 -0
- lmcache/v1/cache_controller/controllers/kv_controller.py +439 -0
- lmcache/v1/cache_controller/controllers/registration_controller.py +282 -0
- lmcache/v1/cache_controller/executor.py +463 -0
- lmcache/v1/cache_controller/frontend/static/css/style.css +201 -0
- lmcache/v1/cache_controller/frontend/static/img/logo.png +0 -0
- lmcache/v1/cache_controller/frontend/static/index.html +234 -0
- lmcache/v1/cache_controller/frontend/static/js/controller_app.js +660 -0
- lmcache/v1/cache_controller/full_sync_sender.py +475 -0
- lmcache/v1/cache_controller/locks.py +149 -0
- lmcache/v1/cache_controller/message.py +828 -0
- lmcache/v1/cache_controller/observability.py +208 -0
- lmcache/v1/cache_controller/utils.py +679 -0
- lmcache/v1/cache_controller/worker.py +665 -0
- lmcache/v1/cache_engine.py +2058 -0
- lmcache/v1/cache_interface.py +19 -0
- lmcache/v1/check/__init__.py +74 -0
- lmcache/v1/check/check_mode_gen.py +86 -0
- lmcache/v1/check/check_mode_test_l2_adapter.py +284 -0
- lmcache/v1/check/check_mode_test_remote.py +155 -0
- lmcache/v1/check/check_mode_test_storage_manager.py +142 -0
- lmcache/v1/check/utils.py +571 -0
- lmcache/v1/compute/__init__.py +2 -0
- lmcache/v1/compute/attention/__init__.py +0 -0
- lmcache/v1/compute/attention/abstract.py +39 -0
- lmcache/v1/compute/attention/flash_attn.py +129 -0
- lmcache/v1/compute/attention/flash_infer_sparse.py +284 -0
- lmcache/v1/compute/attention/metadata.py +85 -0
- lmcache/v1/compute/attention/utils.py +14 -0
- lmcache/v1/compute/blend/__init__.py +7 -0
- lmcache/v1/compute/blend/blender.py +168 -0
- lmcache/v1/compute/blend/metadata.py +34 -0
- lmcache/v1/compute/blend/utils.py +63 -0
- lmcache/v1/compute/models/__init__.py +0 -0
- lmcache/v1/compute/models/base.py +141 -0
- lmcache/v1/compute/models/llama.py +9 -0
- lmcache/v1/compute/models/qwen3.py +24 -0
- lmcache/v1/compute/models/utils.py +68 -0
- lmcache/v1/compute/positional_encoding.py +199 -0
- lmcache/v1/config.py +848 -0
- lmcache/v1/config_base.py +848 -0
- lmcache/v1/distributed/api.py +248 -0
- lmcache/v1/distributed/config.py +321 -0
- lmcache/v1/distributed/error.py +64 -0
- lmcache/v1/distributed/eviction.py +192 -0
- lmcache/v1/distributed/eviction_policy/__init__.py +21 -0
- lmcache/v1/distributed/eviction_policy/factory.py +27 -0
- lmcache/v1/distributed/eviction_policy/lru.py +244 -0
- lmcache/v1/distributed/eviction_policy/noop.py +50 -0
- lmcache/v1/distributed/internal_api.py +170 -0
- lmcache/v1/distributed/l1_manager.py +835 -0
- lmcache/v1/distributed/l2_adapters/__init__.py +67 -0
- lmcache/v1/distributed/l2_adapters/base.py +360 -0
- lmcache/v1/distributed/l2_adapters/config.py +385 -0
- lmcache/v1/distributed/l2_adapters/factory.py +205 -0
- lmcache/v1/distributed/l2_adapters/fs_l2_adapter.py +747 -0
- lmcache/v1/distributed/l2_adapters/fs_native_l2_adapter.py +167 -0
- lmcache/v1/distributed/l2_adapters/mock_l2_adapter.py +516 -0
- lmcache/v1/distributed/l2_adapters/mooncake_store_l2_adapter.py +135 -0
- lmcache/v1/distributed/l2_adapters/native_connector_l2_adapter.py +468 -0
- lmcache/v1/distributed/l2_adapters/native_plugin_l2_adapter.py +199 -0
- lmcache/v1/distributed/l2_adapters/nixl_store_dynamic_l2_adapter.py +831 -0
- lmcache/v1/distributed/l2_adapters/nixl_store_l2_adapter.py +983 -0
- lmcache/v1/distributed/l2_adapters/plugin_l2_adapter.py +210 -0
- lmcache/v1/distributed/l2_adapters/resp_l2_adapter.py +176 -0
- lmcache/v1/distributed/memory_manager.py +179 -0
- lmcache/v1/distributed/storage_controller.py +39 -0
- lmcache/v1/distributed/storage_controllers/__init__.py +43 -0
- lmcache/v1/distributed/storage_controllers/eviction_controller.py +242 -0
- lmcache/v1/distributed/storage_controllers/prefetch_controller.py +830 -0
- lmcache/v1/distributed/storage_controllers/prefetch_policy.py +193 -0
- lmcache/v1/distributed/storage_controllers/store_controller.py +452 -0
- lmcache/v1/distributed/storage_controllers/store_policy.py +213 -0
- lmcache/v1/distributed/storage_manager.py +532 -0
- lmcache/v1/event_manager.py +145 -0
- lmcache/v1/exceptions/__init__.py +16 -0
- lmcache/v1/gpu_connector/__init__.py +126 -0
- lmcache/v1/gpu_connector/gpu_connectors.py +1906 -0
- lmcache/v1/gpu_connector/gpu_ops.py +85 -0
- lmcache/v1/gpu_connector/hpu_connector.py +326 -0
- lmcache/v1/gpu_connector/mock_gpu_connector.py +67 -0
- lmcache/v1/gpu_connector/utils.py +890 -0
- lmcache/v1/gpu_connector/xpu_connectors.py +916 -0
- lmcache/v1/health_monitor/__init__.py +1 -0
- lmcache/v1/health_monitor/base.py +587 -0
- lmcache/v1/health_monitor/checks/__init__.py +1 -0
- lmcache/v1/health_monitor/checks/remote_backend_check.py +304 -0
- lmcache/v1/health_monitor/constants.py +36 -0
- lmcache/v1/internal_api_server/__init__.py +0 -0
- lmcache/v1/internal_api_server/api_registry.py +59 -0
- lmcache/v1/internal_api_server/api_server.py +120 -0
- lmcache/v1/internal_api_server/common/__init__.py +1 -0
- lmcache/v1/internal_api_server/common/env_api.py +22 -0
- lmcache/v1/internal_api_server/common/loglevel_api.py +57 -0
- lmcache/v1/internal_api_server/common/metrics_api.py +29 -0
- lmcache/v1/internal_api_server/common/periodic_thread_api.py +138 -0
- lmcache/v1/internal_api_server/common/run_script_api.py +73 -0
- lmcache/v1/internal_api_server/common/thread_api.py +63 -0
- lmcache/v1/internal_api_server/controller/__init__.py +1 -0
- lmcache/v1/internal_api_server/controller/key_stats_api.py +81 -0
- lmcache/v1/internal_api_server/controller/worker_info_api.py +136 -0
- lmcache/v1/internal_api_server/utils.py +43 -0
- lmcache/v1/internal_api_server/vllm/__init__.py +1 -0
- lmcache/v1/internal_api_server/vllm/backend_api.py +221 -0
- lmcache/v1/internal_api_server/vllm/bypass_api.py +204 -0
- lmcache/v1/internal_api_server/vllm/cache_api.py +895 -0
- lmcache/v1/internal_api_server/vllm/chunk_statistics_api.py +141 -0
- lmcache/v1/internal_api_server/vllm/conf_api.py +147 -0
- lmcache/v1/internal_api_server/vllm/freeze_api.py +172 -0
- lmcache/v1/internal_api_server/vllm/hot_cache_api.py +184 -0
- lmcache/v1/internal_api_server/vllm/inference_api.py +65 -0
- lmcache/v1/internal_api_server/vllm/load_fs_chunks_api.py +320 -0
- lmcache/v1/internal_api_server/vllm/lookup_api.py +145 -0
- lmcache/v1/internal_api_server/vllm/version_api.py +25 -0
- lmcache/v1/kv_layer_groups.py +267 -0
- lmcache/v1/lazy_memory_allocator.py +284 -0
- lmcache/v1/lookup_client/__init__.py +25 -0
- lmcache/v1/lookup_client/abstract_client.py +77 -0
- lmcache/v1/lookup_client/async_lookup_message.py +50 -0
- lmcache/v1/lookup_client/chunk_statistics_lookup_client.py +200 -0
- lmcache/v1/lookup_client/factory.py +251 -0
- lmcache/v1/lookup_client/hit_limit_lookup_client.py +86 -0
- lmcache/v1/lookup_client/lmcache_async_lookup_client.py +407 -0
- lmcache/v1/lookup_client/lmcache_lookup_client.py +285 -0
- lmcache/v1/lookup_client/lmcache_lookup_client_bypass.py +99 -0
- lmcache/v1/lookup_client/mooncake_lookup_client.py +87 -0
- lmcache/v1/lookup_client/record_strategies/__init__.py +77 -0
- lmcache/v1/lookup_client/record_strategies/base.py +327 -0
- lmcache/v1/lookup_client/record_strategies/file_hash.py +130 -0
- lmcache/v1/lookup_client/record_strategies/memory_bloom_filter.py +81 -0
- lmcache/v1/manager.py +539 -0
- lmcache/v1/memory_management.py +2619 -0
- lmcache/v1/metadata.py +114 -0
- lmcache/v1/mp_observability/AGENTS.override.md +21 -0
- lmcache/v1/mp_observability/README.md +204 -0
- lmcache/v1/mp_observability/config.py +340 -0
- lmcache/v1/mp_observability/event.py +100 -0
- lmcache/v1/mp_observability/event_bus.py +313 -0
- lmcache/v1/mp_observability/otel_init.py +145 -0
- lmcache/v1/mp_observability/subscribers/__init__.py +28 -0
- lmcache/v1/mp_observability/subscribers/logging/__init__.py +19 -0
- lmcache/v1/mp_observability/subscribers/logging/l1.py +56 -0
- lmcache/v1/mp_observability/subscribers/logging/l2.py +73 -0
- lmcache/v1/mp_observability/subscribers/logging/lookup_hash.py +209 -0
- lmcache/v1/mp_observability/subscribers/logging/mp_server.py +90 -0
- lmcache/v1/mp_observability/subscribers/logging/sm.py +59 -0
- lmcache/v1/mp_observability/subscribers/metrics/__init__.py +20 -0
- lmcache/v1/mp_observability/subscribers/metrics/l0_lifecycle.py +290 -0
- lmcache/v1/mp_observability/subscribers/metrics/l1.py +55 -0
- lmcache/v1/mp_observability/subscribers/metrics/l1_lifecycle.py +166 -0
- lmcache/v1/mp_observability/subscribers/metrics/l2.py +121 -0
- lmcache/v1/mp_observability/subscribers/metrics/sm.py +69 -0
- lmcache/v1/mp_observability/subscribers/tracing/__init__.py +12 -0
- lmcache/v1/mp_observability/subscribers/tracing/mp_server.py +333 -0
- lmcache/v1/mp_observability/subscribers/tracing/span_registry.py +148 -0
- lmcache/v1/mp_observability/trace/__init__.py +50 -0
- lmcache/v1/mp_observability/trace/codecs.py +255 -0
- lmcache/v1/mp_observability/trace/decorator.py +147 -0
- lmcache/v1/mp_observability/trace/format.py +132 -0
- lmcache/v1/mp_observability/trace/lifecycle.py +83 -0
- lmcache/v1/mp_observability/trace/reader.py +167 -0
- lmcache/v1/mp_observability/trace/recorder.py +300 -0
- lmcache/v1/multiprocess/__init__.py +0 -0
- lmcache/v1/multiprocess/affinity_pool.py +102 -0
- lmcache/v1/multiprocess/blend_server_v2.py +891 -0
- lmcache/v1/multiprocess/config.py +253 -0
- lmcache/v1/multiprocess/custom_types.py +281 -0
- lmcache/v1/multiprocess/futures.py +194 -0
- lmcache/v1/multiprocess/gpu_context.py +511 -0
- lmcache/v1/multiprocess/http_server.py +235 -0
- lmcache/v1/multiprocess/mp_runtime_plugin_launcher.py +130 -0
- lmcache/v1/multiprocess/mq.py +732 -0
- lmcache/v1/multiprocess/protocol.py +86 -0
- lmcache/v1/multiprocess/protocols/README.md +213 -0
- lmcache/v1/multiprocess/protocols/__init__.py +127 -0
- lmcache/v1/multiprocess/protocols/base.py +89 -0
- lmcache/v1/multiprocess/protocols/blend.py +109 -0
- lmcache/v1/multiprocess/protocols/blend_v2.py +57 -0
- lmcache/v1/multiprocess/protocols/controller.py +53 -0
- lmcache/v1/multiprocess/protocols/debug.py +34 -0
- lmcache/v1/multiprocess/protocols/engine.py +146 -0
- lmcache/v1/multiprocess/protocols/observability.py +39 -0
- lmcache/v1/multiprocess/server.py +1134 -0
- lmcache/v1/multiprocess/session.py +190 -0
- lmcache/v1/multiprocess/token_hasher.py +441 -0
- lmcache/v1/offload_server/__init__.py +17 -0
- lmcache/v1/offload_server/abstract_server.py +37 -0
- lmcache/v1/offload_server/message.py +30 -0
- lmcache/v1/offload_server/zmq_server.py +122 -0
- lmcache/v1/periodic_thread.py +579 -0
- lmcache/v1/pin_monitor.py +246 -0
- lmcache/v1/plugin/__init__.py +0 -0
- lmcache/v1/plugin/runtime_plugin_launcher.py +211 -0
- lmcache/v1/protocol.py +317 -0
- lmcache/v1/rpc/__init__.py +17 -0
- lmcache/v1/rpc/transport.py +105 -0
- lmcache/v1/rpc/zmq_transport.py +213 -0
- lmcache/v1/rpc_utils.py +165 -0
- lmcache/v1/server/__init__.py +2 -0
- lmcache/v1/server/__main__.py +170 -0
- lmcache/v1/server/storage_backend/__init__.py +21 -0
- lmcache/v1/server/storage_backend/abstract_backend.py +80 -0
- lmcache/v1/server/storage_backend/local_backend.py +75 -0
- lmcache/v1/server/utils.py +21 -0
- lmcache/v1/standalone/__init__.py +1 -0
- lmcache/v1/standalone/__main__.py +583 -0
- lmcache/v1/standalone/manager.py +80 -0
- lmcache/v1/standalone/standalone_service_factory.py +86 -0
- lmcache/v1/storage_backend/__init__.py +313 -0
- lmcache/v1/storage_backend/abstract_backend.py +445 -0
- lmcache/v1/storage_backend/audit_backend.py +233 -0
- lmcache/v1/storage_backend/batched_message_sender.py +222 -0
- lmcache/v1/storage_backend/cache_policy/__init__.py +45 -0
- lmcache/v1/storage_backend/cache_policy/base_policy.py +87 -0
- lmcache/v1/storage_backend/cache_policy/fifo.py +58 -0
- lmcache/v1/storage_backend/cache_policy/lfu.py +105 -0
- lmcache/v1/storage_backend/cache_policy/lru.py +81 -0
- lmcache/v1/storage_backend/cache_policy/mru.py +61 -0
- lmcache/v1/storage_backend/connector/__init__.py +443 -0
- lmcache/v1/storage_backend/connector/audit_adapter.py +77 -0
- lmcache/v1/storage_backend/connector/audit_connector.py +320 -0
- lmcache/v1/storage_backend/connector/base_connector.py +379 -0
- lmcache/v1/storage_backend/connector/blackhole_adapter.py +21 -0
- lmcache/v1/storage_backend/connector/blackhole_connector.py +37 -0
- lmcache/v1/storage_backend/connector/eic_adapter.py +31 -0
- lmcache/v1/storage_backend/connector/eic_connector.py +757 -0
- lmcache/v1/storage_backend/connector/external_adapter.py +79 -0
- lmcache/v1/storage_backend/connector/fs_adapter.py +51 -0
- lmcache/v1/storage_backend/connector/fs_connector.py +403 -0
- lmcache/v1/storage_backend/connector/infinistore_adapter.py +56 -0
- lmcache/v1/storage_backend/connector/infinistore_connector.py +177 -0
- lmcache/v1/storage_backend/connector/instrumented_connector.py +219 -0
- lmcache/v1/storage_backend/connector/lm_adapter.py +31 -0
- lmcache/v1/storage_backend/connector/lm_connector.py +176 -0
- lmcache/v1/storage_backend/connector/mock_adapter.py +57 -0
- lmcache/v1/storage_backend/connector/mock_connector.py +349 -0
- lmcache/v1/storage_backend/connector/mooncakestore_adapter.py +43 -0
- lmcache/v1/storage_backend/connector/mooncakestore_connector.py +614 -0
- lmcache/v1/storage_backend/connector/redis_adapter.py +181 -0
- lmcache/v1/storage_backend/connector/redis_connector.py +828 -0
- lmcache/v1/storage_backend/connector/s3_adapter.py +59 -0
- lmcache/v1/storage_backend/connector/s3_connector.py +699 -0
- lmcache/v1/storage_backend/connector/sagemaker_hyperpod_adapter.py +233 -0
- lmcache/v1/storage_backend/connector/sagemaker_hyperpod_connector.py +987 -0
- lmcache/v1/storage_backend/connector/valkey_adapter.py +114 -0
- lmcache/v1/storage_backend/connector/valkey_connector.py +627 -0
- lmcache/v1/storage_backend/gds_backend.py +1199 -0
- lmcache/v1/storage_backend/job_executor/__init__.py +0 -0
- lmcache/v1/storage_backend/job_executor/base_executor.py +34 -0
- lmcache/v1/storage_backend/job_executor/pq_executor.py +235 -0
- lmcache/v1/storage_backend/local_cpu_backend.py +810 -0
- lmcache/v1/storage_backend/local_disk_backend.py +656 -0
- lmcache/v1/storage_backend/maru_backend.py +734 -0
- lmcache/v1/storage_backend/naive_serde/__init__.py +50 -0
- lmcache/v1/storage_backend/naive_serde/cachegen_basics.py +133 -0
- lmcache/v1/storage_backend/naive_serde/cachegen_decoder.py +135 -0
- lmcache/v1/storage_backend/naive_serde/cachegen_encoder.py +83 -0
- lmcache/v1/storage_backend/naive_serde/kivi_serde.py +22 -0
- lmcache/v1/storage_backend/naive_serde/naive_serde.py +18 -0
- lmcache/v1/storage_backend/naive_serde/serde.py +37 -0
- lmcache/v1/storage_backend/native_clients/connector_client_base.py +165 -0
- lmcache/v1/storage_backend/native_clients/resp_client.py +35 -0
- lmcache/v1/storage_backend/nixl_storage_backend.py +1400 -0
- lmcache/v1/storage_backend/p2p_backend.py +788 -0
- lmcache/v1/storage_backend/path_sharder.py +117 -0
- lmcache/v1/storage_backend/pd_backend.py +646 -0
- lmcache/v1/storage_backend/plugins/dax_backend.py +1443 -0
- lmcache/v1/storage_backend/plugins/rust_raw_block_backend.py +1361 -0
- lmcache/v1/storage_backend/remote_backend.py +624 -0
- lmcache/v1/storage_backend/resp_client.py +227 -0
- lmcache/v1/storage_backend/storage_backend_listener.py +19 -0
- lmcache/v1/storage_backend/storage_manager.py +1352 -0
- lmcache/v1/system_detection.py +110 -0
- lmcache/v1/token_database.py +551 -0
- lmcache/v1/transfer_channel/__init__.py +83 -0
- lmcache/v1/transfer_channel/abstract.py +285 -0
- lmcache/v1/transfer_channel/mock_memory_channel.py +156 -0
- lmcache/v1/transfer_channel/nixl_channel.py +639 -0
- lmcache/v1/transfer_channel/py_socket_channel.py +260 -0
- lmcache/v1/transfer_channel/transfer_utils.py +63 -0
- lmcache/v1/utils/__init__.py +1 -0
- lmcache/v1/utils/bloom_filter.py +109 -0
- lmcache/v1/utils/cache_utils.py +125 -0
- lmcache_cli-0.4.5.dev0.dist-info/METADATA +185 -0
- lmcache_cli-0.4.5.dev0.dist-info/RECORD +399 -0
- lmcache_cli-0.4.5.dev0.dist-info/WHEEL +5 -0
- lmcache_cli-0.4.5.dev0.dist-info/entry_points.txt +2 -0
- lmcache_cli-0.4.5.dev0.dist-info/licenses/LICENSE +201 -0
- lmcache_cli-0.4.5.dev0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
# Standard
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from typing import Dict, List, Optional
|
|
6
|
+
from urllib.parse import parse_qs, urlparse
|
|
7
|
+
import asyncio
|
|
8
|
+
import importlib
|
|
9
|
+
import inspect
|
|
10
|
+
import pkgutil
|
|
11
|
+
|
|
12
|
+
# First Party
|
|
13
|
+
from lmcache.logging import init_logger
|
|
14
|
+
from lmcache.v1.config import LMCacheEngineConfig
|
|
15
|
+
from lmcache.v1.metadata import LMCacheMetadata
|
|
16
|
+
from lmcache.v1.storage_backend.connector.base_connector import RemoteConnector
|
|
17
|
+
from lmcache.v1.storage_backend.connector.instrumented_connector import (
|
|
18
|
+
InstrumentedRemoteConnector,
|
|
19
|
+
)
|
|
20
|
+
from lmcache.v1.storage_backend.local_cpu_backend import LocalCPUBackend
|
|
21
|
+
|
|
22
|
+
logger = init_logger(__name__)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass
|
|
26
|
+
class ParsedRemoteURL:
|
|
27
|
+
"""
|
|
28
|
+
The parsed URL of the format:
|
|
29
|
+
<host>:<port>[/path][?query]
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
host: str
|
|
33
|
+
port: int
|
|
34
|
+
path: str
|
|
35
|
+
username: Optional[str] = None
|
|
36
|
+
password: Optional[str] = None
|
|
37
|
+
query_params: Dict[str, List[str]] = field(default_factory=dict)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def parse_remote_url(url: str) -> ParsedRemoteURL:
|
|
41
|
+
"""
|
|
42
|
+
Parses the remote URL into its constituent parts with support for:
|
|
43
|
+
- Multiple hosts (comma-separated)
|
|
44
|
+
- Path and query parameters in each host definition
|
|
45
|
+
- Forward compatibility with legacy format
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
url: The URL to parse
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
ParsedRemoteURL: The parsed URL components
|
|
52
|
+
|
|
53
|
+
Raises:
|
|
54
|
+
ValueError: If the URL is invalid
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
logger.debug(f"Parsing remote URL: {url}")
|
|
58
|
+
parsed = urlparse(url)
|
|
59
|
+
|
|
60
|
+
username = parsed.username
|
|
61
|
+
password = parsed.password
|
|
62
|
+
host = parsed.hostname
|
|
63
|
+
port = parsed.port
|
|
64
|
+
path = parsed.path if parsed.path else ""
|
|
65
|
+
query = parse_qs(parsed.query) if parsed.query else {}
|
|
66
|
+
|
|
67
|
+
assert host is not None, f"Invalid URL {url}: missing host"
|
|
68
|
+
assert port is not None, f"Invalid URL {url}: missing port"
|
|
69
|
+
return ParsedRemoteURL(
|
|
70
|
+
host=host,
|
|
71
|
+
port=port,
|
|
72
|
+
path=path,
|
|
73
|
+
username=username,
|
|
74
|
+
password=password,
|
|
75
|
+
query_params=query,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class SafeLocalCPUBackend(LocalCPUBackend):
|
|
80
|
+
"""
|
|
81
|
+
A safe stub for LocalCPUBackend that can be used when local_cpu_backend is None.
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
def __init__(self, config: LMCacheEngineConfig):
|
|
85
|
+
pass
|
|
86
|
+
|
|
87
|
+
def allocate(self, *args, **kwargs):
|
|
88
|
+
raise RuntimeError(
|
|
89
|
+
"SafeLocalCPUBackend.allocate() should never be called. "
|
|
90
|
+
"This indicates a bug where scheduler role is trying to allocate memory."
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
def __str__(self):
|
|
94
|
+
return "SafeLocalCPUBackend(dummy)"
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def extract_plugin_type(plugin_name: str) -> str:
|
|
98
|
+
"""Extract the type portion from a plugin name.
|
|
99
|
+
|
|
100
|
+
Plugin name format: ``{type}`` or ``{type}.{instance}``.
|
|
101
|
+
Returns the *type* part so that adapters can match by type.
|
|
102
|
+
|
|
103
|
+
Examples:
|
|
104
|
+
>>> extract_plugin_type("fs")
|
|
105
|
+
'fs'
|
|
106
|
+
>>> extract_plugin_type("fs.primary")
|
|
107
|
+
'fs'
|
|
108
|
+
"""
|
|
109
|
+
return plugin_name.split(".", 1)[0]
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class ConnectorContext:
|
|
113
|
+
"""
|
|
114
|
+
Context for creating a connector.
|
|
115
|
+
|
|
116
|
+
Attributes:
|
|
117
|
+
url: The remote URL
|
|
118
|
+
loop: The asyncio event loop
|
|
119
|
+
local_cpu_backend: The local CPU backend
|
|
120
|
+
(wrapped as SafeLocalCPUBackend if None)
|
|
121
|
+
config: Optional LMCache engine configuration
|
|
122
|
+
plugin_name: Optional plugin instance name
|
|
123
|
+
(e.g. "fs", "fs.primary")
|
|
124
|
+
"""
|
|
125
|
+
|
|
126
|
+
def __init__(
|
|
127
|
+
self,
|
|
128
|
+
url: str,
|
|
129
|
+
loop: asyncio.AbstractEventLoop,
|
|
130
|
+
local_cpu_backend: Optional[LocalCPUBackend],
|
|
131
|
+
config: Optional[LMCacheEngineConfig],
|
|
132
|
+
metadata: Optional[LMCacheMetadata],
|
|
133
|
+
plugin_name: Optional[str] = None,
|
|
134
|
+
):
|
|
135
|
+
self.url = url
|
|
136
|
+
self.loop = loop
|
|
137
|
+
# Wrap None as SafeLocalCPUBackend to satisfy type requirements
|
|
138
|
+
# The SafeLocalCPUBackend will raise an error if allocate() is called
|
|
139
|
+
self.local_cpu_backend: LocalCPUBackend = (
|
|
140
|
+
local_cpu_backend
|
|
141
|
+
if local_cpu_backend is not None
|
|
142
|
+
else SafeLocalCPUBackend(config)
|
|
143
|
+
)
|
|
144
|
+
self.config = config
|
|
145
|
+
self.metadata = metadata
|
|
146
|
+
self.plugin_name = plugin_name
|
|
147
|
+
|
|
148
|
+
def get_full_chunk_size_bytes(self) -> int:
|
|
149
|
+
"""
|
|
150
|
+
return the number of bytes in a full chunk
|
|
151
|
+
useful for S3Connector where we need to preallocate filesystem buffers
|
|
152
|
+
in ramfs for zero-copy transfers
|
|
153
|
+
"""
|
|
154
|
+
return self.local_cpu_backend.get_full_chunk_size_bytes()
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class ConnectorAdapter(ABC):
|
|
158
|
+
"""Base class for connector adapters."""
|
|
159
|
+
|
|
160
|
+
def __init__(self, schema: str = "") -> None:
|
|
161
|
+
self.schema = schema
|
|
162
|
+
|
|
163
|
+
def can_parse(self, url: str) -> bool:
|
|
164
|
+
return self.schema != "" and url.startswith(self.schema)
|
|
165
|
+
|
|
166
|
+
@abstractmethod
|
|
167
|
+
def create_connector(self, context: ConnectorContext) -> RemoteConnector:
|
|
168
|
+
"""
|
|
169
|
+
Create a connector using the given context.
|
|
170
|
+
"""
|
|
171
|
+
pass
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
class DynamicConnectorAdapter(ConnectorAdapter):
|
|
175
|
+
"""Adapter that wraps a RemoteConnector class loaded
|
|
176
|
+
dynamically from plugin config.
|
|
177
|
+
|
|
178
|
+
When ``class_name`` points to a ``RemoteConnector`` subclass
|
|
179
|
+
rather than a ``ConnectorAdapter``, this wrapper is used to
|
|
180
|
+
instantiate the connector with the proper context.
|
|
181
|
+
"""
|
|
182
|
+
|
|
183
|
+
def __init__(
|
|
184
|
+
self,
|
|
185
|
+
plugin_name: str,
|
|
186
|
+
connector_class: type,
|
|
187
|
+
) -> None:
|
|
188
|
+
schema = "plugin://%s" % extract_plugin_type(plugin_name)
|
|
189
|
+
super().__init__(schema)
|
|
190
|
+
self._plugin_name = plugin_name
|
|
191
|
+
self._connector_class = connector_class
|
|
192
|
+
|
|
193
|
+
def can_parse(self, url: str) -> bool:
|
|
194
|
+
if url.startswith(self.schema):
|
|
195
|
+
return True
|
|
196
|
+
if url.startswith("plugin://"):
|
|
197
|
+
pname = url[len("plugin://") :]
|
|
198
|
+
return extract_plugin_type(pname) == extract_plugin_type(self._plugin_name)
|
|
199
|
+
return False
|
|
200
|
+
|
|
201
|
+
def create_connector(self, context: ConnectorContext) -> RemoteConnector:
|
|
202
|
+
logger.info(
|
|
203
|
+
"Creating dynamic connector %s via %s",
|
|
204
|
+
self._plugin_name,
|
|
205
|
+
self._connector_class.__name__,
|
|
206
|
+
)
|
|
207
|
+
return self._connector_class(
|
|
208
|
+
loop=context.loop,
|
|
209
|
+
local_cpu_backend=context.local_cpu_backend,
|
|
210
|
+
config=context.config,
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
class ConnectorManager:
|
|
215
|
+
"""
|
|
216
|
+
Manager for creating connectors based on URL.
|
|
217
|
+
|
|
218
|
+
This class maintains a registry of connector adapters and creates
|
|
219
|
+
the appropriate connector based on the URL.
|
|
220
|
+
"""
|
|
221
|
+
|
|
222
|
+
def __init__(
|
|
223
|
+
self,
|
|
224
|
+
url: str,
|
|
225
|
+
loop: asyncio.AbstractEventLoop,
|
|
226
|
+
local_cpu_backend: Optional[LocalCPUBackend],
|
|
227
|
+
config: Optional[LMCacheEngineConfig] = None,
|
|
228
|
+
metadata: Optional[LMCacheMetadata] = None,
|
|
229
|
+
plugin_name: Optional[str] = None,
|
|
230
|
+
) -> None:
|
|
231
|
+
logger.info("Initializing ConnectorManager")
|
|
232
|
+
self.context = ConnectorContext(
|
|
233
|
+
url=url,
|
|
234
|
+
loop=loop,
|
|
235
|
+
local_cpu_backend=local_cpu_backend,
|
|
236
|
+
config=config,
|
|
237
|
+
metadata=metadata,
|
|
238
|
+
plugin_name=plugin_name,
|
|
239
|
+
)
|
|
240
|
+
self.adapters: List[ConnectorAdapter] = []
|
|
241
|
+
self._remote_adapters_builtin_launcher()
|
|
242
|
+
self._remote_adapters_plugin_launcher(config)
|
|
243
|
+
|
|
244
|
+
def _remote_adapters_builtin_launcher(self) -> None:
|
|
245
|
+
"""Automatically load all builtin remote connector adapters."""
|
|
246
|
+
# Import current package to ensure all modules are loaded
|
|
247
|
+
# First Party
|
|
248
|
+
import lmcache.v1.storage_backend.connector as connector_pkg
|
|
249
|
+
|
|
250
|
+
# Discover all modules in the connector package
|
|
251
|
+
for _, module_name, _ in pkgutil.iter_modules(connector_pkg.__path__):
|
|
252
|
+
# Skip private modules and non-adapter modules
|
|
253
|
+
if module_name.startswith("_") or not module_name.endswith("_adapter"):
|
|
254
|
+
continue
|
|
255
|
+
|
|
256
|
+
try:
|
|
257
|
+
module = importlib.import_module(
|
|
258
|
+
f"{connector_pkg.__name__}.{module_name}"
|
|
259
|
+
)
|
|
260
|
+
|
|
261
|
+
# Find all ConnectorAdapter subclasses in the module
|
|
262
|
+
for _, obj in inspect.getmembers(module):
|
|
263
|
+
if (
|
|
264
|
+
inspect.isclass(obj)
|
|
265
|
+
and issubclass(obj, ConnectorAdapter)
|
|
266
|
+
and obj != ConnectorAdapter
|
|
267
|
+
):
|
|
268
|
+
try:
|
|
269
|
+
adapter_instance = obj()
|
|
270
|
+
self.adapters.append(adapter_instance)
|
|
271
|
+
logger.info(f"Discovered adapter: {obj.__name__}")
|
|
272
|
+
except Exception as e:
|
|
273
|
+
logger.error(
|
|
274
|
+
"Failed to instantiate adapter "
|
|
275
|
+
f"{obj.__name__}: {str(e)}"
|
|
276
|
+
)
|
|
277
|
+
except ImportError as e:
|
|
278
|
+
logger.warning(f"Failed to import module {module_name}: {e}")
|
|
279
|
+
|
|
280
|
+
def _remote_adapters_plugin_launcher(self, config: LMCacheEngineConfig) -> None:
|
|
281
|
+
"""Automatically load all plug and play remote connector adapters."""
|
|
282
|
+
|
|
283
|
+
if config is None:
|
|
284
|
+
logger.warning(
|
|
285
|
+
"Configuration not available to parse remote connector adapters."
|
|
286
|
+
)
|
|
287
|
+
return
|
|
288
|
+
|
|
289
|
+
# Get the list of allowed remote connector adapters if configured
|
|
290
|
+
remote_storage_plugins = (
|
|
291
|
+
set(config.remote_storage_plugins)
|
|
292
|
+
if config.remote_storage_plugins
|
|
293
|
+
else set()
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
for remote_storage_plugin in remote_storage_plugins:
|
|
297
|
+
try:
|
|
298
|
+
extra_config = config.extra_config
|
|
299
|
+
|
|
300
|
+
module_path = (
|
|
301
|
+
extra_config.get(
|
|
302
|
+
"remote_storage_plugin.%s.module_path" % remote_storage_plugin
|
|
303
|
+
)
|
|
304
|
+
if extra_config
|
|
305
|
+
else None
|
|
306
|
+
)
|
|
307
|
+
class_name = (
|
|
308
|
+
extra_config.get(
|
|
309
|
+
"remote_storage_plugin.%s.class_name" % remote_storage_plugin
|
|
310
|
+
)
|
|
311
|
+
if extra_config
|
|
312
|
+
else None
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
if not module_path or not class_name:
|
|
316
|
+
# Skip silently when a builtin adapter
|
|
317
|
+
# already handles this plugin type.
|
|
318
|
+
plugin_url = "plugin://%s" % remote_storage_plugin
|
|
319
|
+
if any(a.can_parse(plugin_url) for a in self.adapters):
|
|
320
|
+
continue
|
|
321
|
+
logger.warning(
|
|
322
|
+
"Remote connector %s missing adapter module_path or class_name",
|
|
323
|
+
remote_storage_plugin,
|
|
324
|
+
)
|
|
325
|
+
continue
|
|
326
|
+
|
|
327
|
+
# Dynamically import the module
|
|
328
|
+
module = importlib.import_module(module_path)
|
|
329
|
+
# Get the class from the module
|
|
330
|
+
loaded_class = getattr(module, class_name)
|
|
331
|
+
|
|
332
|
+
if inspect.isclass(loaded_class) and issubclass(
|
|
333
|
+
loaded_class, ConnectorAdapter
|
|
334
|
+
):
|
|
335
|
+
adapter_instance = loaded_class()
|
|
336
|
+
elif inspect.isclass(loaded_class) and issubclass(
|
|
337
|
+
loaded_class, RemoteConnector
|
|
338
|
+
):
|
|
339
|
+
adapter_instance = DynamicConnectorAdapter(
|
|
340
|
+
plugin_name=remote_storage_plugin,
|
|
341
|
+
connector_class=loaded_class,
|
|
342
|
+
)
|
|
343
|
+
else:
|
|
344
|
+
logger.warning(
|
|
345
|
+
"Remote connector %s class %s is "
|
|
346
|
+
"neither a ConnectorAdapter nor a "
|
|
347
|
+
"RemoteConnector subclass",
|
|
348
|
+
remote_storage_plugin,
|
|
349
|
+
class_name,
|
|
350
|
+
)
|
|
351
|
+
continue
|
|
352
|
+
self.adapters.append(adapter_instance)
|
|
353
|
+
logger.info(
|
|
354
|
+
"Discovered adapter: %s",
|
|
355
|
+
loaded_class.__name__,
|
|
356
|
+
)
|
|
357
|
+
except (ImportError, AttributeError) as e:
|
|
358
|
+
logger.error(
|
|
359
|
+
f"Failed to load remote connector {remote_storage_plugin} due to "
|
|
360
|
+
f"import/attribute error: {e}"
|
|
361
|
+
)
|
|
362
|
+
except Exception as e:
|
|
363
|
+
logger.error(
|
|
364
|
+
f"Failed to create remote connector {remote_storage_plugin} "
|
|
365
|
+
f"adapter: {str(e)}"
|
|
366
|
+
)
|
|
367
|
+
|
|
368
|
+
def create_connector(self) -> RemoteConnector:
|
|
369
|
+
for adapter in self.adapters:
|
|
370
|
+
if adapter.can_parse(self.context.url):
|
|
371
|
+
logger.info(f"Creating connector for URL: {self.context.url}")
|
|
372
|
+
connector = adapter.create_connector(self.context)
|
|
373
|
+
return connector
|
|
374
|
+
|
|
375
|
+
raise ValueError(f"No adapter found for URL: {self.context.url}")
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
def CreateConnector(
|
|
379
|
+
url: str,
|
|
380
|
+
loop: asyncio.AbstractEventLoop,
|
|
381
|
+
local_cpu_backend: Optional[LocalCPUBackend],
|
|
382
|
+
config: Optional[LMCacheEngineConfig] = None,
|
|
383
|
+
metadata: Optional[LMCacheMetadata] = None,
|
|
384
|
+
plugin_name: Optional[str] = None,
|
|
385
|
+
) -> InstrumentedRemoteConnector:
|
|
386
|
+
"""
|
|
387
|
+
Create a remote connector from the given URL.
|
|
388
|
+
|
|
389
|
+
Supported URL formats:
|
|
390
|
+
- redis://[[username]:[password]@]host[:port][/database][?option=value]
|
|
391
|
+
- rediss://[[username]:[password]@]host[:port][/database][?option=value] (SSL)
|
|
392
|
+
- redis-sentinel://[[username]:[password]@]host1:port1[,host2:port2,...]/service_name
|
|
393
|
+
- lm://host:port
|
|
394
|
+
- infinistore://host:port[?device=device_name]
|
|
395
|
+
- mooncakestore://host:port[?device=device_name]
|
|
396
|
+
- blackhole://[any_text]
|
|
397
|
+
- audit://host:port[?verify=true|false]
|
|
398
|
+
- fs://[host:port]/path
|
|
399
|
+
- s3://[bucket].s3express-[az_id].[region].amazonaws.com"
|
|
400
|
+
- mock://[capacity]/?peeking_latency=[ms]&read_throughput=[GB/s]&write_throughput=[GB/s]
|
|
401
|
+
or
|
|
402
|
+
- s3://[bucket].s3.[region].amazonaws.com
|
|
403
|
+
|
|
404
|
+
Examples:
|
|
405
|
+
- redis://localhost:6379
|
|
406
|
+
- rediss://user:password@redis.example.com:6380/0
|
|
407
|
+
- redis-sentinel://user:password@sentinel1:26379,sentinel2:26379/mymaster
|
|
408
|
+
- lm://localhost:65432
|
|
409
|
+
- infinistore://127.0.0.1:12345?device=mlx5_0
|
|
410
|
+
- mooncakestore://127.0.0.1:50051
|
|
411
|
+
- blackhole://
|
|
412
|
+
- audit://localhost:8080?verify=true
|
|
413
|
+
- fs:///tmp/lmcache
|
|
414
|
+
- external://host:0/external_log_connector.lmc_external_log_connector/?connector_name=ExternalLogConnector
|
|
415
|
+
- s3://fakefile--use1-az4--x-s3.s3express-use1-az4.us-east-1.amazonaws.com
|
|
416
|
+
- mock://100/?peeking_latency=1&read_throughput=2&write_throughput=2
|
|
417
|
+
or
|
|
418
|
+
- s3://fakefile--use1-az4--x-s3.s3.us-east-1.amazonaws.com
|
|
419
|
+
|
|
420
|
+
Args:
|
|
421
|
+
url: The remote URL
|
|
422
|
+
loop: The asyncio event loop
|
|
423
|
+
local_cpu_backend: The local CPU backend (can be None for scheduler role)
|
|
424
|
+
config: Optional LMCache engine configuration
|
|
425
|
+
metadata: Optional LMCache engine metadata
|
|
426
|
+
|
|
427
|
+
Returns:
|
|
428
|
+
RemoteConnector: The created connector
|
|
429
|
+
|
|
430
|
+
Raises:
|
|
431
|
+
ValueError: If the connector cannot be created
|
|
432
|
+
"""
|
|
433
|
+
|
|
434
|
+
# Basic URL validation - check for scheme
|
|
435
|
+
if "://" not in url:
|
|
436
|
+
raise ValueError(f"Invalid remote url {url}: missing scheme")
|
|
437
|
+
|
|
438
|
+
manager = ConnectorManager(
|
|
439
|
+
url, loop, local_cpu_backend, config, metadata, plugin_name
|
|
440
|
+
)
|
|
441
|
+
connector = manager.create_connector()
|
|
442
|
+
|
|
443
|
+
return InstrumentedRemoteConnector(connector)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
# First Party
|
|
3
|
+
from lmcache.logging import init_logger
|
|
4
|
+
from lmcache.v1.storage_backend.connector import (
|
|
5
|
+
ConnectorAdapter,
|
|
6
|
+
ConnectorContext,
|
|
7
|
+
CreateConnector,
|
|
8
|
+
parse_remote_url,
|
|
9
|
+
)
|
|
10
|
+
from lmcache.v1.storage_backend.connector.base_connector import RemoteConnector
|
|
11
|
+
|
|
12
|
+
logger = init_logger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class AuditConnectorAdapter(ConnectorAdapter):
|
|
16
|
+
"""Adapter for Audit connectors (for debugging and verification)."""
|
|
17
|
+
|
|
18
|
+
def __init__(self) -> None:
|
|
19
|
+
super().__init__("audit://")
|
|
20
|
+
|
|
21
|
+
def create_connector(self, context: ConnectorContext) -> RemoteConnector:
|
|
22
|
+
# Local
|
|
23
|
+
from .audit_connector import AuditConnector
|
|
24
|
+
|
|
25
|
+
"""
|
|
26
|
+
Create an Audit connector. This connector wraps another connector
|
|
27
|
+
and audits all operations.
|
|
28
|
+
|
|
29
|
+
extra_config:
|
|
30
|
+
- audit_actual_remote_url: The actual remote URL to connect to.
|
|
31
|
+
- audit_calc_checksum: Whether to calculate checksums.
|
|
32
|
+
- audit_verify_checksum: Whether to verify checksums.
|
|
33
|
+
|
|
34
|
+
URL format:
|
|
35
|
+
- audit://host:port[?verify=true|false]
|
|
36
|
+
|
|
37
|
+
Examples:
|
|
38
|
+
- audit://localhost:8080
|
|
39
|
+
- audit://audit-server.example.com:8080?verify=true
|
|
40
|
+
- audit://127.0.0.1:8080?verify=false
|
|
41
|
+
"""
|
|
42
|
+
logger.info(f"Creating Audit connector for URL: {context.url}")
|
|
43
|
+
hosts = context.url.split(",")
|
|
44
|
+
if len(hosts) > 1:
|
|
45
|
+
raise ValueError(
|
|
46
|
+
f"Only one host is supported for audit connector, but got {hosts}"
|
|
47
|
+
)
|
|
48
|
+
if not context.config:
|
|
49
|
+
raise ValueError("Config is not set")
|
|
50
|
+
|
|
51
|
+
parse_url = parse_remote_url(context.url)
|
|
52
|
+
# (Deprecated) verify URL parameter will be removed in future versions
|
|
53
|
+
# Use the extra config instead
|
|
54
|
+
verify_param = parse_url.query_params.get("verify", ["false"])[0]
|
|
55
|
+
verify_checksum = verify_param.lower() in ("true", "1", "yes")
|
|
56
|
+
# Get the actual remote URL from the extra config first to keep consistency
|
|
57
|
+
real_url = context.config.extra_config.get(
|
|
58
|
+
"audit_actual_remote_url", context.config.audit_actual_remote_url
|
|
59
|
+
)
|
|
60
|
+
if not real_url:
|
|
61
|
+
raise ValueError(
|
|
62
|
+
"audit_actual_remote_url is not set in the config or extra_config"
|
|
63
|
+
)
|
|
64
|
+
# Store verify_checksum in extra_config if not already set
|
|
65
|
+
if context.config.extra_config is None:
|
|
66
|
+
context.config.extra_config = {}
|
|
67
|
+
if "audit_verify_checksum" not in context.config.extra_config:
|
|
68
|
+
context.config.extra_config["audit_verify_checksum"] = verify_checksum
|
|
69
|
+
connector = CreateConnector(
|
|
70
|
+
real_url,
|
|
71
|
+
context.loop,
|
|
72
|
+
context.local_cpu_backend,
|
|
73
|
+
context.config,
|
|
74
|
+
context.metadata,
|
|
75
|
+
)
|
|
76
|
+
# Metaclass dynamically implements all abstract methods at runtime
|
|
77
|
+
return AuditConnector(connector.getWrappedConnector(), context.config) # type: ignore[abstract]
|