tgstation-server 6.12.0
The /tg/station 13 server suite
Loading...
Searching...
No Matches
DeploymentLockManager.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Generic;
3using System.Globalization;
4using System.Runtime.CompilerServices;
5using System.Text;
6using System.Threading.Tasks;
7
8using Microsoft.Extensions.Logging;
9
11
13{
18 {
23
27 readonly ILogger logger;
28
33
37 readonly HashSet<DmbLock> locks;
38
43
54 public static DeploymentLockManager Create(IDmbProvider dmbProvider, ILogger logger, string initialLockReason, out IDmbProvider firstLock, [CallerFilePath] string? callerFile = null, [CallerLineNumber] int callerLine = default)
55 {
56 var manager = new DeploymentLockManager(dmbProvider, logger, initialLockReason, callerFile!, callerLine);
57 firstLock = manager.firstLock;
58 return manager;
59 }
60
66 static string GetFullLockDescriptor(DmbLock dmbLock) => $"{dmbLock.LockID} {dmbLock.Descriptor} (Created at {dmbLock.LockTime}){(dmbLock.KeptAlive ? " (RELEASED)" : String.Empty)}";
67
77 DeploymentLockManager(IDmbProvider dmbProvider, ILogger logger, string initialLockReason, string callerFile, int callerLine)
78 {
79 this.dmbProvider = dmbProvider ?? throw new ArgumentNullException(nameof(dmbProvider));
80 this.logger = logger ?? throw new ArgumentNullException(nameof(logger));
81
82 logger.LogTrace("Initializing lock manager for compile job {id}", dmbProvider.CompileJob.Id);
83 locks = new HashSet<DmbLock>();
84 firstLock = CreateLock(initialLockReason, callerFile, callerLine);
85 }
86
88 public ValueTask DisposeAsync()
90
98 public IDmbProvider AddLock(string reason, [CallerFilePath] string? callerFile = null, [CallerLineNumber]int callerLine = default)
99 {
100 ArgumentNullException.ThrowIfNull(reason);
101 lock (locks)
102 {
103 if (locks.Count == 0)
104 throw new InvalidOperationException($"No locks exist on the DmbProvider for CompileJob {dmbProvider.CompileJob.Id}!");
105
106 return CreateLock(reason, callerFile!, callerLine);
107 }
108 }
109
114 public void LogLockStats(StringBuilder stringBuilder)
115 {
116 ArgumentNullException.ThrowIfNull(stringBuilder);
117
118 stringBuilder.AppendLine(CultureInfo.InvariantCulture, $"Compile Job #{CompileJob.Id}: {CompileJob.DirectoryName}");
119 lock (locks)
120 foreach (var dmbLock in locks)
121 stringBuilder.AppendLine(CultureInfo.InvariantCulture, $"\t-{GetFullLockDescriptor(dmbLock)}");
122 }
123
132 DmbLock CreateLock(string reason, string callerFile, int callerLine)
133 {
134 DmbLock? newLock = null;
135 string? descriptor = null;
136 ValueTask LockCleanupAction()
137 {
138 ValueTask disposeTask = ValueTask.CompletedTask;
139 lock (locks)
140 {
141 logger.LogTrace("Removing .dmb Lock: {descriptor}", descriptor);
142
143 if (locks.Remove(newLock!))
144 logger.LogTrace("Lock was removed from list successfully");
145 else
146 logger.LogError("A .dmb lock was disposed more than once: {descriptor}", descriptor);
147
148 if (locks.Count == 0)
149 disposeTask = dmbProvider.DisposeAsync();
150 else if (newLock == firstLock)
151 logger.LogDebug("First lock on CompileJob #{compileJobId} removed, it must cleanup {remaining} remaining locks to be cleaned", CompileJob.Id, locks.Count);
152 }
153
154 return disposeTask;
155 }
156
157 newLock = new DmbLock(LockCleanupAction, dmbProvider, $"{callerFile}#{callerLine}: {reason}");
158 locks.Add(newLock);
159
160 descriptor = GetFullLockDescriptor(newLock!);
161 logger.LogTrace("Created .dmb Lock: {descriptor}", descriptor);
162
163 return newLock;
164 }
165 }
166}
virtual ? long Id
The ID of the entity.
Definition EntityId.cs:13
readonly DmbLock firstLock
The first lock acquired by the DeploymentLockManager.
static string GetFullLockDescriptor(DmbLock dmbLock)
Generates a verbose description of a given dmbLock .
IDmbProvider AddLock(string reason, [CallerFilePath] string? callerFile=null, [CallerLineNumber]int callerLine=default)
Add a lock to the managed IDmbProvider.
static DeploymentLockManager Create(IDmbProvider dmbProvider, ILogger logger, string initialLockReason, out IDmbProvider firstLock, [CallerFilePath] string? callerFile=null, [CallerLineNumber] int callerLine=default)
Create a DeploymentLockManager.
readonly ILogger logger
The ILogger for the DeploymentLockManager.
void LogLockStats(StringBuilder stringBuilder)
Add lock stats to a given stringBuilder .
readonly HashSet< DmbLock > locks
The DmbLocks on the dmbProvider.
readonly IDmbProvider dmbProvider
The IDmbProvider the DeploymentLockManager is managing.
DmbLock CreateLock(string reason, string callerFile, int callerLine)
Creates a DmbLock and adds it to locks.
DeploymentLockManager(IDmbProvider dmbProvider, ILogger logger, string initialLockReason, string callerFile, int callerLine)
Initializes a new instance of the DeploymentLockManager class.
Represents a lock on a given IDmbProvider.
Definition DmbLock.cs:13
Provides absolute paths to the latest compiled .dmbs.
Models.CompileJob CompileJob
The CompileJob of the .dmb.