vdm/ids.hpp — TaskId, an opaque engine handle (DAEMON keeps the wire UUID <-> TaskId map; the engine never sees the UUID). segment/segmenter — per-download range management (docs/04 §3). Initial lazy split; assign_slot() splits the largest remaining range when the budget grants a slot; on_complete(may_steal) either *steals* the second half of the largest remaining range for the same worker (slot-neutral) or returns nullopt so the caller *yields* the slot (ADR 0011 A1); on_failed() returns requeue only on the 3rd consecutive connection error with a mirror present — the remaining range is orphaned and re-split. Non-resumable or unknown-size => exactly 1 segment; never split below min_segment_bytes (1 MiB). Resume ctor rebuilds from a persisted table (falls back to a fresh layout if it doesn't tile [0,total)). One mutex == "the task lock"; segment fields are std::atomic and the store is a std::deque so a steal's append never moves a worker's record. segment/budget — the global allocator (ADR 0011). Owns exactly one ceiling (maxActiveSegments) and min-1-before-seconds fairness: a two-pass allocation (guarantee pass gives every wanting task 1 slot in DAEMON's priority order, then a growth pass round-robins the rest up to each task's effective cap = min(per_task_cap, host cap, 1 if non-resumable)), recomputed from scratch on every edge so a live set_max_active_segments cut naturally yields the excess lowest-priority-first, never a mid-segment kill. DAEMON-facing surface exactly as promised in daemon/docs/core-requests-m1.md / ADR 0011: budget(), segments_active(), starved_tasks(), starved_since(), set_max_active_segments (drain), set_host_segment_cap, set_task_order, on_budget_changed (a jthread coalesces at <=4 Hz; the tasks_starved 0<->nonzero edge fires immediately). Callbacks are copied out and run after the lock is dropped. Tests: segmenter split/steal/requeue/resume math + a concurrent steal-and-advance run; budget min-1 under a tight budget, round-robin growth, host-cap and non-resumable clamps, live-lower shedding lowest-priority-first, starvation below the task count, starved-edge notification, and a concurrent set_want hammer. Green under ASan/UBSan; the steal path and the budget green under TSan. Co-Authored-By: Claude Sonnet 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01HPPSGhiArbvQgwC2DNiURS
79 lines
3.2 KiB
CMake
79 lines
3.2 KiB
CMake
# core/ produces TWO targets (ADR 0009):
|
|
# veloxcore — the download engine. No JSON, no SQL, no Qt, no RPC. Ever (CLAUDE.md §3).
|
|
# veloxproto — the generated wire types, which ARE JSON. NOT linked by veloxcore.
|
|
# The `no JSON in core/` rule constrains core/src/ and core/include/; core/generated/ is
|
|
# the sanctioned exception. Wired in by PKG via add_subdirectory(core) in the root file.
|
|
|
|
find_package(Threads REQUIRED)
|
|
find_package(CURL 8.0 REQUIRED)
|
|
|
|
add_library(veloxcore STATIC
|
|
src/util/error.cpp
|
|
src/util/log.cpp
|
|
src/util/thread_pool.cpp
|
|
src/net/curl_error.cpp
|
|
src/net/http_client.cpp
|
|
src/net/text_codec.cpp
|
|
src/net/content_disposition.cpp
|
|
src/net/url.cpp
|
|
src/net/probe.cpp
|
|
src/io/sparse_file.cpp
|
|
src/io/write_buffer.cpp
|
|
src/meta/veloxpart.cpp
|
|
src/segment/segmenter.cpp
|
|
src/segment/budget.cpp
|
|
)
|
|
add_library(velox::core ALIAS veloxcore)
|
|
|
|
target_include_directories(veloxcore
|
|
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
|
|
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src # net/*.cpp -> "net/curl_error.hpp"
|
|
)
|
|
|
|
target_compile_features(veloxcore PUBLIC cxx_std_23)
|
|
|
|
# Warnings are set at target scope, not via CMAKE_CXX_FLAGS: the dev/tsan presets
|
|
# overwrite that cache variable wholesale (see core/docs/pkg-requests-m1.md P4).
|
|
target_compile_options(veloxcore PRIVATE
|
|
-Wall -Wextra -Wpedantic -Werror
|
|
)
|
|
|
|
target_link_libraries(veloxcore PUBLIC Threads::Threads CURL::libcurl)
|
|
|
|
# Later stages add: find_package(OpenSSL) for meta/ (streaming SHA-256 + resume CRC).
|
|
|
|
# --- libveloxproto — generated wire code (ADR 0009) --------------------------------------
|
|
# Its own target so libveloxcore stays JSON-free. Consumed by veloxd, the CLI, the GUI and
|
|
# the conformance runner. The root CMakeLists only find_package(nlohmann_json)'s when
|
|
# daemon/ has landed, so find it here too — this must build even if core is the only lane.
|
|
if(NOT TARGET nlohmann_json::nlohmann_json)
|
|
find_package(nlohmann_json 3.11 REQUIRED)
|
|
endif()
|
|
|
|
add_library(veloxproto STATIC generated/velox_proto.cpp)
|
|
add_library(velox::proto ALIAS veloxproto)
|
|
|
|
target_include_directories(veloxproto PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/generated)
|
|
target_compile_features(veloxproto PUBLIC cxx_std_23)
|
|
target_link_libraries(veloxproto PUBLIC nlohmann_json::nlohmann_json)
|
|
|
|
# Generated code is committed and never hand-edited (CLAUDE.md §2); do not fail the build
|
|
# on a codegen quirk that trips -Werror. Warnings stay on for visibility.
|
|
target_compile_options(veloxproto PRIVATE -Wall -Wextra -Wno-error)
|
|
|
|
# A build-time tripwire for the split ADR 0009 exists to protect: veloxcore must never end
|
|
# up linking veloxproto.
|
|
get_target_property(_core_links veloxcore LINK_LIBRARIES)
|
|
if(_core_links AND "veloxproto" IN_LIST _core_links)
|
|
message(FATAL_ERROR "veloxcore links veloxproto — ADR 0009 violation (engine sees JSON).")
|
|
endif()
|
|
|
|
if(VELOX_BUILD_TESTS)
|
|
add_subdirectory(tests)
|
|
endif()
|
|
|
|
# Fuzz targets live in ${CMAKE_SOURCE_DIR}/tools/fuzz (lane CORE) and are wired in by the
|
|
# top-level CMakeLists.txt, which add_subdirectory()s every tools/* with a CMakeLists.
|
|
# tools/fuzz/CMakeLists.txt self-guards on VELOX_BUILD_FUZZ + a Clang compiler.
|
|
# Present: Content-Disposition, URL (stage 3). Coming: .veloxpart.meta (stage 5).
|