29#include <shared_mutex>
63 default:
return "unknown";
71 -> std::optional<lock_type> {
99 std::optional<std::chrono::system_clock::time_point>
expires_at;
106 return std::chrono::system_clock::now() < *
expires_at;
120 -> std::optional<std::chrono::milliseconds> {
122 auto now = std::chrono::system_clock::now();
123 if (now >= *
expires_at)
return std::chrono::milliseconds{0};
124 return std::chrono::duration_cast<std::chrono::milliseconds>(
152 std::optional<std::chrono::system_clock::time_point>
expires_at;
160 [[nodiscard]]
auto duration() const -> std::chrono::milliseconds {
161 return std::chrono::duration_cast<std::chrono::milliseconds>(
170 return std::chrono::system_clock::now() >= *
expires_at;
250namespace lock_error {
381 [[nodiscard]] auto
lock(
382 const std::
string& study_uid,
383 const std::
string& reason,
384 const std::
string& holder = "",
385 std::chrono::seconds timeout = std::chrono::seconds{0})
398 [[nodiscard]]
auto lock(
399 const std::string& study_uid,
401 const std::string& reason,
402 const std::string& holder =
"",
403 std::chrono::seconds timeout = std::chrono::seconds{0})
417 const std::string& study_uid,
419 const std::string& reason,
420 const std::string& holder =
"",
421 std::chrono::seconds timeout = std::chrono::seconds{0})
434 [[nodiscard]]
auto unlock(
const lock_token& token)
444 [[nodiscard]]
auto unlock(
445 const std::string& study_uid,
446 const std::string& holder)
457 const std::string& study_uid,
458 const std::string& admin_reason =
"")
479 [[nodiscard]]
auto is_locked(
const std::string& study_uid)
const -> bool;
489 const std::string& study_uid,
498 [[nodiscard]]
auto get_lock_info(
const std::string& study_uid)
const
499 -> std::optional<lock_info>;
508 -> std::optional<lock_info>;
516 [[nodiscard]]
auto validate_token(
const lock_token& token)
const -> bool;
526 const lock_token& token,
527 std::chrono::seconds extension = std::chrono::seconds{0})
539 [[nodiscard]]
auto get_all_locks() const -> std::vector<lock_info>;
548 -> std::vector<lock_info>;
557 -> std::vector<lock_info>;
582 [[nodiscard]] auto
get_stats() const -> lock_manager_stats;
594 [[nodiscard]] auto
get_config() const -> const study_lock_manager_config&;
603 void set_config(const study_lock_manager_config& config);
611 const std::
string& study_uid,
657 [[nodiscard]] auto
resolve_holder(const std::
string& holder) const
664 -> std::optional<std::chrono::system_clock::time_point>;
670 const std::
string& study_uid,
Manages locks on DICOM studies for concurrent access control.
auto calculate_expiry(std::chrono::seconds timeout) const -> std::optional< std::chrono::system_clock::time_point >
Calculate expiration time.
auto is_locked(const std::string &study_uid) const -> bool
Check if a study is locked.
void set_on_lock_expired(lock_event_callback callback)
Set callback for lock expiration events.
std::function< void( const std::string &study_uid, const lock_info &info)> lock_event_callback
Callback type for lock events.
auto force_unlock(const std::string &study_uid, const std::string &admin_reason="") -> kcenon::common::Result< std::monostate >
Force release a lock (admin operation)
study_lock_manager()
Construct lock manager with default configuration.
std::map< std::string, lock_entry > locks_
Lock entries (study_uid -> lock_entry)
auto get_locks_by_type(lock_type type) const -> std::vector< lock_info >
Get all locks of a specific type.
lock_event_callback on_lock_released_
auto get_lock_info(const std::string &study_uid) const -> std::optional< lock_info >
Get lock information for a study.
study_lock_manager & operator=(const study_lock_manager &)=delete
void set_on_lock_released(lock_event_callback callback)
Set callback for lock release events.
auto get_stats() const -> lock_manager_stats
Get lock manager statistics.
void reset_stats()
Reset statistics counters.
auto unlock_all_by_holder(const std::string &holder) -> std::size_t
Release all locks held by a specific holder.
auto get_config() const -> const study_lock_manager_config &
Get the current configuration.
study_lock_manager(const study_lock_manager &)=delete
Non-copyable.
lock_event_callback on_lock_acquired_
Event callbacks.
auto lock(const std::string &study_uid, const std::string &reason, const std::string &holder="", std::chrono::seconds timeout=std::chrono::seconds{0}) -> kcenon::common::Result< lock_token >
Acquire an exclusive lock on a study.
auto resolve_holder(const std::string &holder) const -> std::string
Get holder identifier (uses thread ID if empty)
void set_on_lock_acquired(lock_event_callback callback)
Set callback for lock acquisition events.
auto get_all_locks() const -> std::vector< lock_info >
Get all currently held locks.
auto unlock(const lock_token &token) -> kcenon::common::Result< std::monostate >
Release a lock using its token.
void record_acquisition(lock_type type)
Update statistics on lock acquisition.
auto get_locks_by_holder(const std::string &holder) const -> std::vector< lock_info >
Get all locks held by a specific holder.
~study_lock_manager()
Destructor - releases all locks.
auto get_lock_info_by_token(const std::string &token_id) const -> std::optional< lock_info >
Get lock information by token ID.
auto generate_token_id() const -> std::string
Generate a unique token ID.
std::map< std::string, std::string > token_to_study_
Token to study UID mapping for fast lookup.
auto try_lock(const std::string &study_uid, lock_type type, const std::string &reason, const std::string &holder="", std::chrono::seconds timeout=std::chrono::seconds{0}) -> kcenon::common::Result< lock_token >
Try to acquire a lock without blocking.
std::mutex stats_mutex_
Mutex for statistics.
std::atomic< uint64_t > next_token_id_
Next token ID counter.
auto validate_token(const lock_token &token) const -> bool
Validate a lock token.
auto can_acquire_lock(const std::string &study_uid, lock_type type) const -> bool
Check if a lock can be acquired.
std::shared_mutex mutex_
Mutex for thread-safe access.
lock_event_callback on_lock_expired_
auto get_expired_locks() const -> std::vector< lock_info >
Get all expired locks.
study_lock_manager_config config_
Configuration.
auto refresh_lock(const lock_token &token, std::chrono::seconds extension=std::chrono::seconds{0}) -> kcenon::common::Result< lock_token >
Refresh a lock (extend its timeout)
auto cleanup_expired_locks() -> std::size_t
Clean up expired locks.
void record_release(lock_type type, std::chrono::milliseconds duration)
Update statistics on lock release.
lock_manager_stats stats_
Statistics.
void set_config(const study_lock_manager_config &config)
Update configuration.
std::shared_mutex mutex
Mutex for thread-safe access.
constexpr int max_shared_exceeded
Maximum shared locks exceeded.
constexpr int permission_denied
Permission denied (force unlock not allowed)
constexpr int upgrade_failed
Cannot upgrade lock (shared to exclusive)
constexpr int invalid_type
Invalid lock type.
constexpr int expired
Lock has expired.
constexpr int already_locked
Lock already held by another holder.
constexpr int invalid_token
Invalid token.
constexpr int timeout
Lock timeout exceeded.
constexpr int not_found
Lock not found.
lock_type
Type of lock to acquire on a study.
@ shared
Read-only access allowed (for read operations)
@ exclusive
No other access allowed (for modifications)
@ migration
Special lock for migration operations (highest priority)
auto to_string(lock_type type) -> std::string
Convert lock_type to string.
auto parse_lock_type(const std::string &str) -> std::optional< lock_type >
Parse lock_type from string.
Detailed information about a lock on a study.
lock_type type
Type of lock held.
std::size_t shared_count
Number of shared lock holders (for shared locks)
std::string token_id
Lock token ID.
std::string reason
Reason for the lock.
std::chrono::system_clock::time_point acquired_at
When the lock was acquired.
auto is_expired() const -> bool
Check if the lock has expired.
std::string holder
Who holds the lock (user/service identifier)
std::string study_uid
Study UID that is locked.
std::optional< std::chrono::system_clock::time_point > expires_at
When the lock expires (if timeout set)
auto duration() const -> std::chrono::milliseconds
Get lock duration.
Statistics for lock manager operations.
std::size_t force_unlock_count
Locks that were forcibly released.
std::chrono::milliseconds avg_lock_duration
Average lock duration.
std::size_t total_acquisitions
Total locks acquired.
std::chrono::milliseconds max_lock_duration
Maximum lock duration observed.
std::size_t active_locks
Number of currently held locks.
std::size_t shared_locks
Number of shared locks.
std::size_t exclusive_locks
Number of exclusive locks.
std::size_t migration_locks
Number of migration locks.
std::size_t contention_count
Number of lock contention events.
std::size_t total_releases
Total locks released.
std::size_t timeout_count
Lock acquisitions that timed out.
Unique identifier for a lock.
std::string token_id
Unique token ID.
std::string study_uid
Study UID that is locked.
auto is_expired() const -> bool
Check if the token has expired.
std::optional< std::chrono::system_clock::time_point > expires_at
When the lock expires (if timeout set)
auto remaining_time() const -> std::optional< std::chrono::milliseconds >
Get remaining time until expiration.
auto is_valid() const -> bool
Check if the token is valid (not expired)
std::chrono::system_clock::time_point acquired_at
When the lock was acquired.
lock_type type
Type of lock held.
std::vector< std::string > shared_holders
Configuration for the study lock manager.
std::chrono::seconds default_timeout
Default lock timeout (0 = no timeout)
std::size_t max_shared_locks
Maximum number of concurrent shared locks.
std::chrono::seconds cleanup_interval
How often to check for expired locks.
bool allow_force_unlock
Allow force unlock for admin operations.
bool auto_cleanup
Enable automatic cleanup of expired locks.
std::chrono::milliseconds acquire_wait_timeout
Maximum time to wait when trying to acquire a lock.