Files
DP44/enriched-qwen3-coder-next/Common/DTS.Common/Classes/Locking.md
2026-04-17 14:55:32 -04:00

8.2 KiB
Raw Blame History

source_files, generated_at, model, schema_version, sha256
source_files generated_at model schema_version sha256
Common/DTS.Common/Classes/Locking/LockRecord.cs
Common/DTS.Common/Classes/Locking/LockError.cs
Common/DTS.Common/Classes/Locking/SensorsLocking.cs
2026-04-16T03:16:01.173429+00:00 Qwen/Qwen3-Coder-Next-FP8 1 4c9a49fc0d53b85f

Locking

Documentation: DTS.Common.Classes.Locking Module


1. Purpose

This module provides infrastructure for managing application-level locks on sensor-related data items within a distributed system. It defines core data structures (LockRecord, LockError) to represent lock state and error conditions, and a high-level locking coordinator (SensorsLocking) responsible for maintaining and validating locks on behalf of UI components (e.g., sensor editing controls). The module supports lock renewal, theft detection, and loss handling, integrating with logging (APILogger), event aggregation (Prism.Events), and a lower-level LockManager (referenced but not included here) for persistence operations.


2. Public Interface

LockRecord Class

Represents a single active lock on a data item.

  • Constructor

    public LockRecord(string user, string machine, DateTime createTime, DateTime lastUpdate, string itemKey, int itemCategory, int itemId)
    

    Initializes a new lock record with the specified metadata. All properties are read-only after construction.

  • Properties

    • string LockingUserName Name of the user who acquired the lock.
    • string LockingMachineName Hostname of the machine holding the lock.
    • DateTime CreationTime Timestamp when the lock was first acquired.
    • DateTime LastUpdated Timestamp of the last lock renewal/maintenance.
    • string ItemKey Human-readable key identifying the locked item (e.g., sensor name).
    • int ItemCategory Numeric category of the item (e.g., LockCategories enum value in DB).
    • int ItemId Numeric ID of the locked item (e.g., sensor ID).

LockError Class

Encapsulates error information from lock operations.

  • Constructor

    public LockError(int error, string message, string user = null, string machine = null)
    

    Creates an error instance with code, message, and optional lock holder details.

  • Properties

    • int ErrorCode Numeric error code (see constants below).
    • string Message Human-readable description.
    • string LockingUser User associated with the lock at time of error (empty if unknown).
    • string LockingMachine Machine associated with the lock at time of error (empty if unknown).
    • bool LockStolen => ErrorCode == LOCKSTOLEN_ERROR Indicates the lock was forcibly released by another user.
    • bool LockLost => ErrorCode == LOCKDOESNTEXIST_ERROR Indicates the lock no longer exists in the backing store.
  • Constants

    • BAD_NETPATH_ERROR = 994 Network path error (e.g., lost remote DB connection).
    • SEM_TIMEOUT_ERROR = 995 Semaphore timeout (e.g., connection failure).
    • ITEM_NOT_FOUND = 996 Referenced item not found.
    • LOCKDOESNTEXIST_ERROR = 997 Lock record missing (lock lost).
    • LOCKSTOLEN_ERROR = 998 Lock stolen by another user.
    • UNKNOWN_ERROR = 999 Generic/unspecified error.

SensorsLocking Class

Manages lock lifecycle for sensor UI controls.

  • Unlock(bool bCheckLock, string userName, int userId)
    Stops background lock renewal and attempts to release all tracked locks via FreeLocks(). Logs exceptions but does not propagate them.
    Note: Parameter bCheckLock is unused in the current implementation.

  • IsCurrentlyLocked(LockRecord lockRecord)

    public bool IsCurrentlyLocked(LockRecord lockRecord)
    

    Returns true if the provided lockRecord matches an item currently tracked by this instance (i.e., ItemId and ItemCategory match any entry in _existingLocks). Thread-safe via MyLock.

  • Private Methods (Referenced)

    • StopUpdating() Cancels background renewal task and waits up to MAX_WAIT_TIME_MS (10s) for completion. Returns true only if stopped cleanly.
    • FreeLocks() Iterates over _existingLocks and calls LockManager.FreeLoc for each (implementation truncated in source).
    • CheckLocks(bool publishErrors, string userName, int userId) Validates all tracked locks; on failure, clears _existingLocks, calls WipeOutChanges(), and publishes PageErrorEvent if publishErrors is true.
    • CheckLock(...) Not implemented (NotImplementedException).
    • WipeOutChanges() Not implemented (NotImplementedException).
    • GetErrorMessage(LockError[] errors, LockRecord[] lockRecords) Builds a localized error message string for display, handling LockStolen and LockLost cases.

3. Invariants

  • _existingLocks is always null or a non-null array (never partially initialized).
  • Lock records in _existingLocks are only modified or cleared under the MyLock synchronization object.
  • LockRecord instances are immutable after construction (all properties are readonly or get-only).
  • LockError.ErrorCode is set once at construction and never modified.
  • Lock renewal/maintenance is performed periodically via _updateTask; failure to renew triggers CheckLocks() failure.
  • On any lock failure during CheckLocks(), _existingLocks is atomically reset to an empty array, and WipeOutChanges() is called (though implementation is missing).
  • LockManager.FreeLoc is assumed to be the canonical method for releasing locks (external dependency).

4. Dependencies

Internal Dependencies (from imports)

  • DTS.Common.Events For PageErrorEvent and PageErrorArg.
  • DTS.Common.SharedResource.Strings For localized strings (StringResources.FailedToUpdateLock, LockStolen_Sensors, LockLost_Sensors).
  • DTS.Common.Utilities.Logging For APILogger.
  • Prism.Events For IEventAggregator and ContainerLocator.Container.
  • System.Threading.Tasks For Task, CancellationTokenSource.

External Dependencies (inferred)

  • LockManager Referenced in FreeLocks() but not defined in the provided source. Critical dependency for lock acquisition/release.
  • PageErrorEvent A Prism event used to publish UI-level errors.
  • ContainerLocator.Container Prism/IoC container for resolving services (e.g., IEventAggregator).

Depended Upon By

  • UI controls (e.g., sensor editing forms) that need to track and release locks on sensor items.
  • Likely used in conjunction with LockManager for end-to-end locking workflows.

5. Gotchas

  • CheckLock and WipeOutChanges are unimplemented (NotImplementedException). This module is incomplete and non-functional as-is.
  • bCheckLock parameter in Unlock() is ignored The method always proceeds to FreeLocks() regardless of its value.
  • FreeLocks() calls LockManager.FreeLoc without arguments The source is truncated (FreeLoc call is cut off), so the exact signature and required parameters (e.g., LockRecord) are unknown.
  • GetErrorMessage uses Array.Exists with ItemId/ItemCategory but IsCurrentlyLocked does the same Redundant logic suggests potential for refactoring or inconsistency if LockRecord equality semantics change.
  • No validation of LockRecord constructor parameters No null checks on user, machine, or itemKey; invalid values (e.g., empty ItemKey) may propagate silently.
  • LockingUser/LockingMachine in LockError default to string.Empty Not null, which simplifies UI display but may mask missing data.
  • MAX_WAIT_TIME_MS = 10000 is hardcoded No configuration or override mechanism for timeout duration.
  • Thread-safety relies on MyLock but is inconsistent IsCurrentlyLocked uses lock(MyLock), but CheckLocks and FreeLocks use lock(MyLock) only for reading _existingLocks; background task (_updateTask) state is managed separately.
  • No explicit lock acquisition methods The module only handles renewal and release of already-acquired locks (via LockManager), implying lock acquisition happens elsewhere.

None identified beyond the above.