@dbx-tools/core 0.6.70 → 0.6.72
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.
- package/lib/src/file-lock.d.ts +7 -13
- package/lib/src/file-lock.js +31 -37
- package/package.json +2 -2
- package/src/file-lock.ts +35 -54
package/lib/src/file-lock.d.ts
CHANGED
|
@@ -12,11 +12,14 @@
|
|
|
12
12
|
* Kernel releases the lock when the fd closes (including process death).
|
|
13
13
|
* 2. **file** — atomic lock-directory creation. This is the strategy used by
|
|
14
14
|
* `proper-lockfile`: `mkdir` is atomic on Windows, Unix, and network file
|
|
15
|
-
* systems where `open(..., "wx")` may not be reliable.
|
|
16
|
-
*
|
|
15
|
+
* systems where `open(..., "wx")` may not be reliable. Stale detection is
|
|
16
|
+
* always on (fixed {@link STALE_MS} + heartbeat) so a crashed holder on this
|
|
17
|
+
* backend can be reclaimed.
|
|
17
18
|
*
|
|
18
19
|
* The first backend that can be *initialized* is used for the whole call. A busy
|
|
19
|
-
* lock waits; an unavailable backend falls through to the next.
|
|
20
|
+
* lock waits; an unavailable backend falls through to the next. Callers may only
|
|
21
|
+
* bound how long to wait ({@link FileLockOptions.timeoutMs}); stale timing is
|
|
22
|
+
* not configurable so every holder and waiter agrees.
|
|
20
23
|
*
|
|
21
24
|
* @module
|
|
22
25
|
*/
|
|
@@ -35,18 +38,9 @@ export interface FileLockOptions {
|
|
|
35
38
|
backends?: readonly FileLockBackend[];
|
|
36
39
|
/**
|
|
37
40
|
* Stop waiting and throw after this many milliseconds. Omit to poll forever.
|
|
41
|
+
* This is the only wait-loop knob; stale reclaim timing is fixed.
|
|
38
42
|
*/
|
|
39
43
|
timeoutMs?: number;
|
|
40
|
-
/**
|
|
41
|
-
* Age after which an unrefreshed lock directory may be removed. Omit to
|
|
42
|
-
* disable stale detection. Only used by the `file` backend.
|
|
43
|
-
*/
|
|
44
|
-
staleMs?: number;
|
|
45
|
-
/**
|
|
46
|
-
* Interval for refreshing the lock directory mtime when `staleMs` is set.
|
|
47
|
-
* Defaults to half of `staleMs`.
|
|
48
|
-
*/
|
|
49
|
-
updateMs?: number;
|
|
50
44
|
/** Invoked once the backend for this call has been chosen. */
|
|
51
45
|
onAcquire?: (acquisition: FileLockAcquisition) => void;
|
|
52
46
|
}
|
package/lib/src/file-lock.js
CHANGED
|
@@ -12,11 +12,14 @@
|
|
|
12
12
|
* Kernel releases the lock when the fd closes (including process death).
|
|
13
13
|
* 2. **file** — atomic lock-directory creation. This is the strategy used by
|
|
14
14
|
* `proper-lockfile`: `mkdir` is atomic on Windows, Unix, and network file
|
|
15
|
-
* systems where `open(..., "wx")` may not be reliable.
|
|
16
|
-
*
|
|
15
|
+
* systems where `open(..., "wx")` may not be reliable. Stale detection is
|
|
16
|
+
* always on (fixed {@link STALE_MS} + heartbeat) so a crashed holder on this
|
|
17
|
+
* backend can be reclaimed.
|
|
17
18
|
*
|
|
18
19
|
* The first backend that can be *initialized* is used for the whole call. A busy
|
|
19
|
-
* lock waits; an unavailable backend falls through to the next.
|
|
20
|
+
* lock waits; an unavailable backend falls through to the next. Callers may only
|
|
21
|
+
* bound how long to wait ({@link FileLockOptions.timeoutMs}); stale timing is
|
|
22
|
+
* not configurable so every holder and waiter agrees.
|
|
20
23
|
*
|
|
21
24
|
* @module
|
|
22
25
|
*/
|
|
@@ -36,6 +39,14 @@ const logger = log.logger("core:file-lock");
|
|
|
36
39
|
const DEFAULT_BACKENDS = ["flock", "file"];
|
|
37
40
|
/** Poll interval while waiting for a contended OS lock. */
|
|
38
41
|
const POLL_MS = 50;
|
|
42
|
+
/**
|
|
43
|
+
* Age after which an unrefreshed lock directory may be removed.
|
|
44
|
+
* Matches `proper-lockfile`'s default. Not caller-configurable: every process
|
|
45
|
+
* must share the same threshold or a live holder can be mistaken for stale.
|
|
46
|
+
*/
|
|
47
|
+
const STALE_MS = object.toNumber(process.env.FILE_LOCK_STALE_MS) ?? 10_000;
|
|
48
|
+
/** Heartbeat interval for refreshing lock-directory mtime (`STALE_MS / 2`). */
|
|
49
|
+
const UPDATE_MS = object.toNumber(process.env.FILE_LOCK_UPDATE_MS) ?? STALE_MS / 2;
|
|
39
50
|
/** `flock(2)` operation bits (Linux / macOS / BSD). */
|
|
40
51
|
const LOCK_EX = 2;
|
|
41
52
|
const LOCK_NB = 4;
|
|
@@ -52,7 +63,9 @@ const LOCK_UN = 8;
|
|
|
52
63
|
* });
|
|
53
64
|
*/
|
|
54
65
|
export async function withFileLock(key, fn, options = {}) {
|
|
55
|
-
|
|
66
|
+
if (options.timeoutMs !== undefined && options.timeoutMs < 0) {
|
|
67
|
+
throw new TypeError("timeoutMs must be non-negative");
|
|
68
|
+
}
|
|
56
69
|
const id = lockId(key);
|
|
57
70
|
const backends = options.backends ?? DEFAULT_BACKENDS;
|
|
58
71
|
const dir = options.dir ?? join(tmpdir(), "dbx-tools-locks");
|
|
@@ -74,7 +87,7 @@ export async function withFileLock(key, fn, options = {}) {
|
|
|
74
87
|
const lockPath = join(dir, `${id}.lock`);
|
|
75
88
|
logger.debug("acquiring lock", { backend, key: id, path: lockPath });
|
|
76
89
|
options.onAcquire?.({ backend });
|
|
77
|
-
return holdLockDirectory(lockPath, deadline,
|
|
90
|
+
return holdLockDirectory(lockPath, deadline, fn);
|
|
78
91
|
}
|
|
79
92
|
default: {
|
|
80
93
|
const _exhaustive = backend;
|
|
@@ -84,22 +97,6 @@ export async function withFileLock(key, fn, options = {}) {
|
|
|
84
97
|
}
|
|
85
98
|
throw new Error("withFileLock: no lock backend available");
|
|
86
99
|
}
|
|
87
|
-
function validateOptions(options) {
|
|
88
|
-
if (options.timeoutMs !== undefined && options.timeoutMs < 0) {
|
|
89
|
-
throw new TypeError("timeoutMs must be non-negative");
|
|
90
|
-
}
|
|
91
|
-
if (options.staleMs !== undefined && options.staleMs <= 0) {
|
|
92
|
-
throw new TypeError("staleMs must be positive");
|
|
93
|
-
}
|
|
94
|
-
if (options.updateMs !== undefined) {
|
|
95
|
-
if (options.staleMs === undefined) {
|
|
96
|
-
throw new TypeError("updateMs requires staleMs");
|
|
97
|
-
}
|
|
98
|
-
if (options.updateMs <= 0 || options.updateMs > options.staleMs / 2) {
|
|
99
|
-
throw new TypeError("updateMs must be positive and no greater than half of staleMs");
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
100
|
/** Canonical filesystem-safe id for a lock key. */
|
|
104
101
|
function lockId(key) {
|
|
105
102
|
const stable = object
|
|
@@ -168,13 +165,14 @@ async function waitForFlock(fd, flock, lockPath, deadline) {
|
|
|
168
165
|
* Atomic lock-directory creation — the portable / Windows path.
|
|
169
166
|
*
|
|
170
167
|
* `mkdir` is the same primitive used by `proper-lockfile`: it is atomic across
|
|
171
|
-
* supported local and network filesystems.
|
|
172
|
-
*
|
|
168
|
+
* supported local and network filesystems. The holder refreshes mtime on a fixed
|
|
169
|
+
* heartbeat so a live long-running lock is never reclaimed; a crashed holder's
|
|
170
|
+
* directory becomes reclaimable after {@link STALE_MS}.
|
|
173
171
|
*/
|
|
174
|
-
async function holdLockDirectory(lockPath, deadline,
|
|
172
|
+
async function holdLockDirectory(lockPath, deadline, fn) {
|
|
175
173
|
await ensureParentDir(lockPath);
|
|
176
|
-
await acquireLockDirectory(lockPath, deadline
|
|
177
|
-
const stopHeartbeat = startHeartbeat(lockPath
|
|
174
|
+
await acquireLockDirectory(lockPath, deadline);
|
|
175
|
+
const stopHeartbeat = startHeartbeat(lockPath);
|
|
178
176
|
try {
|
|
179
177
|
return await fn();
|
|
180
178
|
}
|
|
@@ -183,7 +181,7 @@ async function holdLockDirectory(lockPath, deadline, staleMs, updateMs, fn) {
|
|
|
183
181
|
await rm(lockPath, { recursive: true, force: true }).catch(() => { });
|
|
184
182
|
}
|
|
185
183
|
}
|
|
186
|
-
async function acquireLockDirectory(lockPath, deadline
|
|
184
|
+
async function acquireLockDirectory(lockPath, deadline) {
|
|
187
185
|
for (;;) {
|
|
188
186
|
try {
|
|
189
187
|
await mkdir(lockPath);
|
|
@@ -193,18 +191,17 @@ async function acquireLockDirectory(lockPath, deadline, staleMs) {
|
|
|
193
191
|
const err = cause;
|
|
194
192
|
if (err.code !== "EEXIST")
|
|
195
193
|
throw error.toError(cause);
|
|
196
|
-
|
|
197
|
-
await maybeReclaimStale(lockPath, staleMs);
|
|
194
|
+
await maybeReclaimStale(lockPath);
|
|
198
195
|
assertBeforeDeadline(lockPath, deadline);
|
|
199
196
|
await async.sleep(POLL_MS);
|
|
200
197
|
}
|
|
201
198
|
}
|
|
202
199
|
}
|
|
203
|
-
async function maybeReclaimStale(lockPath
|
|
200
|
+
async function maybeReclaimStale(lockPath) {
|
|
204
201
|
try {
|
|
205
202
|
const { mtimeMs } = await stat(lockPath);
|
|
206
203
|
const age = Date.now() - mtimeMs;
|
|
207
|
-
if (age <
|
|
204
|
+
if (age < STALE_MS)
|
|
208
205
|
return;
|
|
209
206
|
logger.debug("reclaiming stale lock directory", { path: lockPath, ageMs: age });
|
|
210
207
|
await rm(lockPath, { recursive: true, force: true });
|
|
@@ -215,10 +212,7 @@ async function maybeReclaimStale(lockPath, staleMs) {
|
|
|
215
212
|
throw error.toError(cause);
|
|
216
213
|
}
|
|
217
214
|
}
|
|
218
|
-
function startHeartbeat(lockPath
|
|
219
|
-
if (staleMs === undefined)
|
|
220
|
-
return () => { };
|
|
221
|
-
const intervalMs = updateMs ?? Math.max(1, Math.floor(staleMs / 2));
|
|
215
|
+
function startHeartbeat(lockPath) {
|
|
222
216
|
const timer = setInterval(() => {
|
|
223
217
|
const now = new Date();
|
|
224
218
|
void utimes(lockPath, now, now).catch((cause) => {
|
|
@@ -227,7 +221,7 @@ function startHeartbeat(lockPath, staleMs, updateMs) {
|
|
|
227
221
|
error: error.errorMessage(cause),
|
|
228
222
|
});
|
|
229
223
|
});
|
|
230
|
-
},
|
|
224
|
+
}, UPDATE_MS);
|
|
231
225
|
timer.unref();
|
|
232
226
|
return () => clearInterval(timer);
|
|
233
227
|
}
|
|
@@ -239,4 +233,4 @@ function assertBeforeDeadline(lockPath, deadline) {
|
|
|
239
233
|
async function ensureParentDir(lockPath) {
|
|
240
234
|
await mkdir(dirname(lockPath), { recursive: true });
|
|
241
235
|
}
|
|
242
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsZS1sb2NrLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2ZpbGUtbG9jay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBcUJHOzs7Ozs7Ozs7QUFFSCxPQUFPLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ2pFLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDakMsT0FBTyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFMUMsT0FBTyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsY0FBYyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFFekYsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0FBSzVDLE1BQU0sZ0JBQWdCLEdBQStCLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBRXZFLDJEQUEyRDtBQUMzRCxNQUFNLE9BQU8sR0FBRyxFQUFFLENBQUM7QUFFbkIsdURBQXVEO0FBQ3ZELE1BQU0sT0FBTyxHQUFHLENBQUMsQ0FBQztBQUNsQixNQUFNLE9BQU8sR0FBRyxDQUFDLENBQUM7QUFDbEIsTUFBTSxPQUFPLEdBQUcsQ0FBQyxDQUFDO0FBMENsQjs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxZQUFZLENBQ2hDLEdBQVksRUFDWixFQUF3QixFQUN4QixVQUEyQixFQUFFO0lBRTdCLGVBQWUsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN6QixNQUFNLEVBQUUsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdkIsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLFFBQVEsSUFBSSxnQkFBZ0IsQ0FBQztJ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RSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0FBQ3RELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENhc2NhZGluZyBjcm9zcy1wcm9jZXNzIG11dHVhbCBleGNsdXNpb24gdmlhIGEgbG9ja2ZpbGUuXG4gKlxuICogU2VyaWFsaXplcyBjb25jdXJyZW50ICpwcm9jZXNzZXMqICh0d28gYGJ1biBydW4gZGVtb2Agc2hlbGxzLCBhIENMSSBiZXNpZGUgYVxuICogc2VydmVyKSBvbiB0aGUgc2FtZSBrZXkuIEZvciBpbi1wcm9jZXNzIC8gd29ya2VyLXRocmVhZCBleGNsdXNpb24gdXNlXG4gKiB7QGxpbmsgd2l0aFByb2Nlc3NMb2NrfSBmcm9tIGAuL3Byb2Nlc3MtbG9jay50c2AgaW5zdGVhZC5cbiAqXG4gKiBCYWNrZW5kcywgaW4gb3JkZXI6XG4gKlxuICogMS4gKipmbG9jayoqIOKAlCBgZmxvY2soMilgIHZpYSBCdW4gRkZJIG9uIFVuaXggd2hlbiBgYnVuOmZmaWAgY2FuIGxvYWQgbGliYy5cbiAqICAgIE5vdCBhdmFpbGFibGUgb24gV2luZG93cywgYW5kIG5vdCBhdmFpbGFibGUgdW5kZXIgcGxhaW4gTm9kZSAobm8gRkZJKS5cbiAqICAgIEtlcm5lbCByZWxlYXNlcyB0aGUgbG9jayB3aGVuIHRoZSBmZCBjbG9zZXMgKGluY2x1ZGluZyBwcm9jZXNzIGRlYXRoKS5cbiAqIDIuICoqZmlsZSoqIOKAlCBhdG9taWMgbG9jay1kaXJlY3RvcnkgY3JlYXRpb24uIFRoaXMgaXMgdGhlIHN0cmF0ZWd5IHVzZWQgYnlcbiAqICAgIGBwcm9wZXItbG9ja2ZpbGVgOiBgbWtkaXJgIGlzIGF0b21pYyBvbiBXaW5kb3dzLCBVbml4LCBhbmQgbmV0d29yayBmaWxlXG4gKiAgICBzeXN0ZW1zIHdoZXJlIGBvcGVuKC4uLiwgXCJ3eFwiKWAgbWF5IG5vdCBiZSByZWxpYWJsZS4gT3B0aW9uYWwgc3RhbGVcbiAqICAgIGRldGVjdGlvbiB1c2VzIHRoZSBkaXJlY3RvcnkgbXRpbWUgcGx1cyBhIGhlYXJ0YmVhdC5cbiAqXG4gKiBUaGUgZmlyc3QgYmFja2VuZCB0aGF0IGNhbiBiZSAqaW5pdGlhbGl6ZWQqIGlzIHVzZWQgZm9yIHRoZSB3aG9sZSBjYWxsLiBBIGJ1c3lcbiAqIGxvY2sgd2FpdHM7IGFuIHVuYXZhaWxhYmxlIGJhY2tlbmQgZmFsbHMgdGhyb3VnaCB0byB0aGUgbmV4dC5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHsgbWtkaXIsIG9wZW4sIHJtLCBzdGF0LCB1dGltZXMgfSBmcm9tIFwibm9kZTpmcy9wcm9taXNlc1wiO1xuaW1wb3J0IHsgdG1wZGlyIH0gZnJvbSBcIm5vZGU6b3NcIjtcbmltcG9ydCB7IGRpcm5hbWUsIGpvaW4gfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5cbmltcG9ydCB7IGFzeW5jLCBlcnJvciwgZnVuY3Rpb25Nb2R1bGUsIGhhc2gsIGxvZywgb2JqZWN0IH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcblxuY29uc3QgbG9nZ2VyID0gbG9nLmxvZ2dlcihcImNvcmU6ZmlsZS1sb2NrXCIpO1xuXG4vKiogQmFja2VuZHMge0BsaW5rIHdpdGhGaWxlTG9ja30gY2FuIGF0dGVtcHQsIGluIGNhc2NhZGUgb3JkZXIuICovXG5leHBvcnQgdHlwZSBGaWxlTG9ja0JhY2tlbmQgPSBcImZsb2NrXCIgfCBcImZpbGVcIjtcblxuY29uc3QgREVGQVVMVF9CQUNLRU5EUzogcmVhZG9ubHkgRmlsZUxvY2tCYWNrZW5kW10gPSBbXCJmbG9ja1wiLCBcImZpbGVcIl07XG5cbi8qKiBQb2xsIGludGVydmFsIHdoaWxlIHdhaXRpbmcgZm9yIGEgY29udGVuZGVkIE9TIGxvY2suICovXG5jb25zdCBQT0xMX01TID0gNTA7XG5cbi8qKiBgZmxvY2soMilgIG9wZXJhdGlvbiBiaXRzIChMaW51eCAvIG1hY09TIC8gQlNEKS4gKi9cbmNvbnN0IExPQ0tfRVggPSAyO1xuY29uc3QgTE9DS19OQiA9IDQ7XG5jb25zdCBMT0NLX1VOID0gODtcblxuLyoqIFJlc3VsdCBtZXRhZGF0YSB3aGVuIGEgY2FsbGVyIHdhbnRzIHRvIGtub3cgd2hpY2ggYmFja2VuZCByYW4uICovXG5leHBvcnQgaW50ZXJmYWNlIEZpbGVMb2NrQWNxdWlzaXRpb24ge1xuICBiYWNrZW5kOiBGaWxlTG9ja0JhY2tlbmQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRmlsZUxvY2tPcHRpb25zIHtcbiAgLyoqXG4gICAqIERpcmVjdG9yeSBmb3IgbG9ja2ZpbGVzLiBEZWZhdWx0cyB0byBgJFRNUERJUi9kYngtdG9vbHMtbG9ja3NgLlxuICAgKi9cbiAgZGlyPzogc3RyaW5nO1xuICAvKiogT3ZlcnJpZGUgdGhlIGNhc2NhZGUuIERlZmF1bHRzIHRvIGBmbG9ja2Ag4oaSIGBmaWxlYC4gKi9cbiAgYmFja2VuZHM/OiByZWFkb25seSBGaWxlTG9ja0JhY2tlbmRbXTtcbiAgLyoqXG4gICAqIFN0b3Agd2FpdGluZyBhbmQgdGhyb3cgYWZ0ZXIgdGhpcyBtYW55IG1pbGxpc2Vjb25kcy4gT21pdCB0byBwb2xsIGZvcmV2ZXIuXG4gICAqL1xuICB0aW1lb3V0TXM/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBBZ2UgYWZ0ZXIgd2hpY2ggYW4gdW5yZWZyZXNoZWQgbG9jayBkaXJlY3RvcnkgbWF5IGJlIHJlbW92ZWQuIE9taXQgdG9cbiAgICogZGlzYWJsZSBzdGFsZSBkZXRlY3Rpb24uIE9ubHkgdXNlZCBieSB0aGUgYGZpbGVgIGJhY2tlbmQuXG4gICAqL1xuICBzdGFsZU1zPzogbnVtYmVyO1xuICAvKipcbiAgICogSW50ZXJ2YWwgZm9yIHJlZnJlc2hpbmcgdGhlIGxvY2sgZGlyZWN0b3J5IG10aW1lIHdoZW4gYHN0YWxlTXNgIGlzIHNldC5cbiAgICogRGVmYXVsdHMgdG8gaGFsZiBvZiBgc3RhbGVNc2AuXG4gICAqL1xuICB1cGRhdGVNcz86IG51bWJlcjtcbiAgLyoqIEludm9rZWQgb25jZSB0aGUgYmFja2VuZCBmb3IgdGhpcyBjYWxsIGhhcyBiZWVuIGNob3Nlbi4gKi9cbiAgb25BY3F1aXJlPzogKGFjcXVpc2l0aW9uOiBGaWxlTG9ja0FjcXVpc2l0aW9uKSA9PiB2b2lkO1xufVxuXG50eXBlIEZsb2NrRm4gPSAoZmQ6IG51bWJlciwgb3BlcmF0aW9uOiBudW1iZXIpID0+IG51bWJlcjtcblxuaW50ZXJmYWNlIEJ1bkZmaU1vZHVsZSB7XG4gIGRsb3BlbjogKFxuICAgIHBhdGg6IHN0cmluZyxcbiAgICBzeW1ib2xzOiBSZWNvcmQ8c3RyaW5nLCB7IGFyZ3M6IHN0cmluZ1tdOyByZXR1cm5zOiBzdHJpbmcgfT4sXG4gICkgPT4geyBzeW1ib2xzOiB7IGZsb2NrOiBGbG9ja0ZuIH0gfTtcbiAgc3VmZml4OiBzdHJpbmc7XG59XG5cbi8qKlxuICogUnVuIGBmbmAgd2hpbGUgaG9sZGluZyBhIGNyb3NzLXByb2Nlc3MgbG9jayBuYW1lZCBieSBga2V5YC5cbiAqXG4gKiBga2V5YCBpcyBjYW5vbmljYWxpemVkIHdpdGggYG9iamVjdC50b1N0YWJsZUtleWAsIHRoZSBzYW1lIGlkZW50aXR5IHJ1bGUgYXNcbiAqIHByb2Nlc3MgYW5kIFBvc3RncmVzIGFkdmlzb3J5IGxvY2tzLlxuICpcbiAqIEBleGFtcGxlXG4gKiBhd2FpdCB3aXRoRmlsZUxvY2soW1wiY2FjaGVcIiwgXCJhcHBraXRcIl0sIGFzeW5jICgpID0+IHtcbiAqICAgYXdhaXQgbWlncmF0ZSgpO1xuICogfSk7XG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB3aXRoRmlsZUxvY2s8VD4oXG4gIGtleTogdW5rbm93bixcbiAgZm46ICgpID0+IFQgfCBQcm9taXNlPFQ+LFxuICBvcHRpb25zOiBGaWxlTG9ja09wdGlvbnMgPSB7fSxcbik6IFByb21pc2U8VD4ge1xuICB2YWxpZGF0ZU9wdGlvbnMob3B0aW9ucyk7XG4gIGNvbnN0IGlkID0gbG9ja0lkKGtleSk7XG4gIGNvbnN0IGJhY2tlbmRzID0gb3B0aW9ucy5iYWNrZW5kcyA/PyBERUZBVUxUX0JBQ0tFTkRTO1xuICBjb25zdCBkaXIgPSBvcHRpb25zLmRpciA/PyBqb2luKHRtcGRpcigpLCBcImRieC10b29scy1sb2Nrc1wiKTtcbiAgY29uc3QgZGVhZGxpbmUgPSBvcHRpb25zLnRpbWVvdXRNcyA9PT0gdW5kZWZpbmVkID8gdW5kZWZpbmVkIDogRGF0ZS5ub3coKSArIG9wdGlvbnMudGltZW91dE1zO1xuXG4gIGZvciAoY29uc3QgYmFja2VuZCBvZiBiYWNrZW5kcykge1xuICAgIHN3aXRjaCAoYmFja2VuZCkge1xuICAgICAgY2FzZSBcImZsb2NrXCI6IHtcbiAgICAgICAgY29uc3QgbG9ja1BhdGggPSBqb2luKGRpciwgYCR7aWR9LmZsb2NrYCk7XG4gICAgICAgIGNvbnN0IGZsb2NrID0gYXdhaXQgcmVzb2x2ZUZsb2NrKCk7XG4gICAgICAgIGlmICghZmxvY2spIHtcbiAgICAgICAgICBsb2dnZXIuZGVidWcoXCJsb2NrIGJhY2tlbmQgdW5hdmFpbGFibGVcIiwgeyBiYWNrZW5kLCBrZXk6IGlkIH0pO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGxvZ2dlci5kZWJ1ZyhcImFjcXVpcmluZyBsb2NrXCIsIHsgYmFja2VuZCwga2V5OiBpZCwgcGF0aDogbG9ja1BhdGggfSk7XG4gICAgICAgIG9wdGlvbnMub25BY3F1aXJlPy4oeyBiYWNrZW5kIH0pO1xuICAgICAgICByZXR1cm4gaG9sZEZsb2NrKGxvY2tQYXRoLCBmbG9jaywgZGVhZGxpbmUsIGZuKTtcbiAgICAgIH1cbiAgICAgIGNhc2UgXCJmaWxlXCI6IHtcbiAgICAgICAgY29uc3QgbG9ja1BhdGggPSBqb2luKGRpciwgYCR7aWR9LmxvY2tgKTtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKFwiYWNxdWlyaW5nIGxvY2tcIiwgeyBiYWNrZW5kLCBrZXk6IGlkLCBwYXRoOiBsb2NrUGF0aCB9KTtcbiAgICAgICAgb3B0aW9ucy5vbkFjcXVpcmU/Lih7IGJhY2tlbmQgfSk7XG4gICAgICAgIHJldHVybiBob2xkTG9ja0RpcmVjdG9yeShsb2NrUGF0aCwgZGVhZGxpbmUsIG9wdGlvbnMuc3RhbGVNcywgb3B0aW9ucy51cGRhdGVNcywgZm4pO1xuICAgICAgfVxuICAgICAgZGVmYXVsdDoge1xuICAgICAgICBjb25zdCBfZXhoYXVzdGl2ZTogbmV2ZXIgPSBiYWNrZW5kO1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYHVua25vd24gZmlsZS1sb2NrIGJhY2tlbmQ6ICR7U3RyaW5nKF9leGhhdXN0aXZlKX1gKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoXCJ3aXRoRmlsZUxvY2s6IG5vIGxvY2sgYmFja2VuZCBhdmFpbGFibGVcIik7XG59XG5cbmZ1bmN0aW9uIHZhbGlkYXRlT3B0aW9ucyhvcHRpb25zOiBGaWxlTG9ja09wdGlvbnMpOiB2b2lkIHtcbiAgaWYgKG9wdGlvbnMudGltZW91dE1zICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy50aW1lb3V0TXMgPCAwKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcInRpbWVvdXRNcyBtdXN0IGJlIG5vbi1uZWdhdGl2ZVwiKTtcbiAgfVxuICBpZiAob3B0aW9ucy5zdGFsZU1zICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy5zdGFsZU1zIDw9IDApIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwic3RhbGVNcyBtdXN0IGJlIHBvc2l0aXZlXCIpO1xuICB9XG4gIGlmIChvcHRpb25zLnVwZGF0ZU1zICE9PSB1bmRlZmluZWQpIHtcbiAgICBpZiAob3B0aW9ucy5zdGFsZU1zID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJ1cGRhdGVNcyByZXF1aXJlcyBzdGFsZU1zXCIpO1xuICAgIH1cbiAgICBpZiAob3B0aW9ucy51cGRhdGVNcyA8PSAwIHx8IG9wdGlvbnMudXBkYXRlTXMgPiBvcHRpb25zLnN0YWxlTXMgLyAyKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwidXBkYXRlTXMgbXVzdCBiZSBwb3NpdGl2ZSBhbmQgbm8gZ3JlYXRlciB0aGFuIGhhbGYgb2Ygc3RhbGVNc1wiKTtcbiAgICB9XG4gIH1cbn1cblxuLyoqIENhbm9uaWNhbCBmaWxlc3lzdGVtLXNhZmUgaWQgZm9yIGEgbG9jayBrZXkuICovXG5mdW5jdGlvbiBsb2NrSWQoa2V5OiB1bmtub3duKTogc3RyaW5nIHtcbiAgY29uc3Qgc3RhYmxlID0gb2JqZWN0XG4gICAgLnRvT25lT3JNYW55KGtleSlcbiAgICAubWFwKChwYXJ0KSA9PiBvYmplY3QudG9TdGFibGVLZXkocGFydCkpXG4gICAgLmpvaW4oXCJcXHUwMDAwXCIpO1xuICAvLyBTaG9ydCBkaWdlc3Qgc28gcGF0aHMgc3RheSB3ZWxsIHVuZGVyIE9TIGxpbWl0czsgY29sbGlzaW9ucyBhcmUgZmluZSDigJQgdGhleVxuICAvLyBvbmx5IG1lcmdlIGNyaXRpY2FsIHNlY3Rpb25zIHRoYXQgYWxyZWFkeSBzaGFyZWQgYSBrZXkgc3RyaW5nLlxuICByZXR1cm4gaGFzaC5mbnZIYXNoKHN0YWJsZSk7XG59XG5cbi8qKlxuICogUmVzb2x2ZSBgZmxvY2soMilgIHRocm91Z2ggQnVuIEZGSSB3aGVuIHBvc3NpYmxlLlxuICpcbiAqIE1lbW9pemVkOiB0aGUgRkZJIGltcG9ydCArIGxpYmMgYGRsb3BlbmAgcnVuIG9uY2UgcGVyIHByb2Nlc3MuIFJldHVybnNcbiAqIGB1bmRlZmluZWRgIG9uIFdpbmRvd3MsIHVuZGVyIHBsYWluIE5vZGUsIG9yIHdoZW4gbGliYyBjYW5ub3QgYmUgbG9hZGVkIOKAlFxuICogY2FsbGVycyBmYWxsIHRocm91Z2ggdG8gdGhlIG5leHQgYmFja2VuZC4gQSBtaXNzIGlzIGNhY2hlZCB0b28sIHNvIGEgcHJvY2Vzc1xuICogdGhhdCBjYW5ub3QgZmxvY2sgbmV2ZXIgcmV0cmllcyB0aGUgbG9hZC5cbiAqL1xuY29uc3QgcmVzb2x2ZUZsb2NrID0gZnVuY3Rpb25Nb2R1bGUubWVtb2l6ZShhc3luYyAoKTogUHJvbWlzZTxGbG9ja0ZuIHwgdW5kZWZpbmVkPiA9PiB7XG4gIGlmIChwcm9jZXNzLnBsYXRmb3JtID09PSBcIndpbjMyXCIpIHJldHVybiB1bmRlZmluZWQ7XG4gIGlmICghcHJvY2Vzcy52ZXJzaW9ucy5idW4pIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgdHJ5IHtcbiAgICAvLyBEeW5hbWljIHNwZWNpZmllciBzbyBgdHNjYCAobm8gYEB0eXBlc2AgZm9yIGBidW46ZmZpYCkgZG9lcyBub3QgcmVzb2x2ZSBpdDtcbiAgICAvLyB0aGUgaW1wb3J0IG9ubHkgc3VjY2VlZHMgdW5kZXIgQnVuIGF0IHJ1bnRpbWUuXG4gICAgY29uc3Qgc3BlY2lmaWVyID0gXCJidW46ZmZpXCI7XG4gICAgY29uc3QgZmZpID0gKGF3YWl0IGltcG9ydChzcGVjaWZpZXIpKSBhcyB1bmtub3duIGFzIEJ1bkZmaU1vZHVsZTtcbiAgICBjb25zdCBsaWJQYXRoID1cbiAgICAgIHByb2Nlc3MucGxhdGZvcm0gPT09IFwiZGFyd2luXCIgPyBcImxpYlN5c3RlbS5CLmR5bGliXCIgOiBgbGliYy4ke2ZmaS5zdWZmaXh9YDtcbiAgICBjb25zdCBsaWIgPSBmZmkuZGxvcGVuKGxpYlBhdGgsIHtcbiAgICAgIGZsb2NrOiB7IGFyZ3M6IFtcImkzMlwiLCBcImkzMlwiXSwgcmV0dXJuczogXCJpMzJcIiB9LFxuICAgIH0pO1xuICAgIHJldHVybiBsaWIuc3ltYm9scy5mbG9jaztcbiAgfSBjYXRjaCAoY2F1c2UpIHtcbiAgICBsb2dnZXIuZGVidWcoXCJmbG9jayBGRkkgdW5hdmFpbGFibGVcIiwgeyBlcnJvcjogZXJyb3IuZXJyb3JNZXNzYWdlKGNhdXNlKSB9KTtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59KTtcblxuYXN5bmMgZnVuY3Rpb24gaG9sZEZsb2NrPFQ+KFxuICBsb2NrUGF0aDogc3RyaW5nLFxuICBmbG9jazogRmxvY2tGbixcbiAgZGVhZGxpbmU6IG51bWJlciB8IHVuZGVmaW5lZCxcbiAgZm46ICgpID0+IFQgfCBQcm9taXNlPFQ+LFxuKTogUHJvbWlzZTxUPiB7XG4gIGF3YWl0IGVuc3VyZVBhcmVudERpcihsb2NrUGF0aCk7XG4gIGNvbnN0IGhhbmRsZSA9IGF3YWl0IG9wZW4obG9ja1BhdGgsIFwiYStcIik7XG4gIHRyeSB7XG4gICAgYXdhaXQgd2FpdEZvckZsb2NrKGhhbmRsZS5mZCwgZmxvY2ssIGxvY2tQYXRoLCBkZWFkbGluZSk7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBhd2FpdCBmbigpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBmbG9jayhoYW5kbGUuZmQsIExPQ0tfVU4pO1xuICAgIH1cbiAgfSBmaW5hbGx5IHtcbiAgICBhd2FpdCBoYW5kbGUuY2xvc2UoKS5jYXRjaCgoKSA9PiB7fSk7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gd2FpdEZvckZsb2NrKFxuICBmZDogbnVtYmVyLFxuICBmbG9jazogRmxvY2tGbixcbiAgbG9ja1BhdGg6IHN0cmluZyxcbiAgZGVhZGxpbmU6IG51bWJlciB8IHVuZGVmaW5lZCxcbik6IFByb21pc2U8dm9pZD4ge1xuICBmb3IgKDs7KSB7XG4gICAgY29uc3QgcmMgPSBmbG9jayhmZCwgTE9DS19FWCB8IExPQ0tfTkIpO1xuICAgIGlmIChyYyA9PT0gMCkgcmV0dXJuO1xuICAgIGFzc2VydEJlZm9yZURlYWRsaW5lKGxvY2tQYXRoLCBkZWFkbGluZSk7XG4gICAgYXdhaXQgYXN5bmMuc2xlZXAoUE9MTF9NUyk7XG4gIH1cbn1cblxuLyoqXG4gKiBBdG9taWMgbG9jay1kaXJlY3RvcnkgY3JlYXRpb24g4oCUIHRoZSBwb3J0YWJsZSAvIFdpbmRvd3MgcGF0aC5cbiAqXG4gKiBgbWtkaXJgIGlzIHRoZSBzYW1lIHByaW1pdGl2ZSB1c2VkIGJ5IGBwcm9wZXItbG9ja2ZpbGVgOiBpdCBpcyBhdG9taWMgYWNyb3NzXG4gKiBzdXBwb3J0ZWQgbG9jYWwgYW5kIG5ldHdvcmsgZmlsZXN5c3RlbXMuIFdoZW4gc3RhbGUgZGV0ZWN0aW9uIGlzIGVuYWJsZWQsXG4gKiB0aGUgaG9sZGVyIHJlZnJlc2hlcyBtdGltZSBzbyBhIGxpdmUgbG9uZy1ydW5uaW5nIGxvY2sgaXMgbmV2ZXIgcmVjbGFpbWVkLlxuICovXG5hc3luYyBmdW5jdGlvbiBob2xkTG9ja0RpcmVjdG9yeTxUPihcbiAgbG9ja1BhdGg6IHN0cmluZyxcbiAgZGVhZGxpbmU6IG51bWJlciB8IHVuZGVmaW5lZCxcbiAgc3RhbGVNczogbnVtYmVyIHwgdW5kZWZpbmVkLFxuICB1cGRhdGVNczogbnVtYmVyIHwgdW5kZWZpbmVkLFxuICBmbjogKCkgPT4gVCB8IFByb21pc2U8VD4sXG4pOiBQcm9taXNlPFQ+IHtcbiAgYXdhaXQgZW5zdXJlUGFyZW50RGlyKGxvY2tQYXRoKTtcbiAgYXdhaXQgYWNxdWlyZUxvY2tEaXJlY3RvcnkobG9ja1BhdGgsIGRlYWRsaW5lLCBzdGFsZU1zKTtcbiAgY29uc3Qgc3RvcEhlYXJ0YmVhdCA9IHN0YXJ0SGVhcnRiZWF0KGxvY2tQYXRoLCBzdGFsZU1zLCB1cGRhdGVNcyk7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGF3YWl0IGZuKCk7XG4gIH0gZmluYWxseSB7XG4gICAgc3RvcEhlYXJ0YmVhdCgpO1xuICAgIGF3YWl0IHJtKGxvY2tQYXRoLCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSkuY2F0Y2goKCkgPT4ge30pO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGFjcXVpcmVMb2NrRGlyZWN0b3J5KFxuICBsb2NrUGF0aDogc3RyaW5nLFxuICBkZWFkbGluZTogbnVtYmVyIHwgdW5kZWZpbmVkLFxuICBzdGFsZU1zOiBudW1iZXIgfCB1bmRlZmluZWQsXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgZm9yICg7Oykge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBta2Rpcihsb2NrUGF0aCk7XG4gICAgICByZXR1cm47XG4gICAgfSBjYXRjaCAoY2F1c2UpIHtcbiAgICAgIGNvbnN0IGVyciA9IGNhdXNlIGFzIE5vZGVKUy5FcnJub0V4Y2VwdGlvbjtcbiAgICAgIGlmIChlcnIuY29kZSAhPT0gXCJFRVhJU1RcIikgdGhyb3cgZXJyb3IudG9FcnJvcihjYXVzZSk7XG4gICAgICBpZiAoc3RhbGVNcyAhPT0gdW5kZWZpbmVkKSBhd2FpdCBtYXliZVJlY2xhaW1TdGFsZShsb2NrUGF0aCwgc3RhbGVNcyk7XG4gICAgICBhc3NlcnRCZWZvcmVEZWFkbGluZShsb2NrUGF0aCwgZGVhZGxpbmUpO1xuICAgICAgYXdhaXQgYXN5bmMuc2xlZXAoUE9MTF9NUyk7XG4gICAgfVxuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG1heWJlUmVjbGFpbVN0YWxlKGxvY2tQYXRoOiBzdHJpbmcsIHN0YWxlTXM6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICB0cnkge1xuICAgIGNvbnN0IHsgbXRpbWVNcyB9ID0gYXdhaXQgc3RhdChsb2NrUGF0aCk7XG4gICAgY29uc3QgYWdlID0gRGF0ZS5ub3coKSAtIG10aW1lTXM7XG4gICAgaWYgKGFnZSA8IHN0YWxlTXMpIHJldHVybjtcbiAgICBsb2dnZXIuZGVidWcoXCJyZWNsYWltaW5nIHN0YWxlIGxvY2sgZGlyZWN0b3J5XCIsIHsgcGF0aDogbG9ja1BhdGgsIGFnZU1zOiBhZ2UgfSk7XG4gICAgYXdhaXQgcm0obG9ja1BhdGgsIHsgcmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZSB9KTtcbiAgfSBjYXRjaCAoY2F1c2UpIHtcbiAgICBjb25zdCBlcnIgPSBjYXVzZSBhcyBOb2RlSlMuRXJybm9FeGNlcHRpb247XG4gICAgaWYgKGVyci5jb2RlICE9PSBcIkVOT0VOVFwiKSB0aHJvdyBlcnJvci50b0Vycm9yKGNhdXNlKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBzdGFydEhlYXJ0YmVhdChcbiAgbG9ja1BhdGg6IHN0cmluZyxcbiAgc3RhbGVNczogbnVtYmVyIHwgdW5kZWZpbmVkLFxuICB1cGRhdGVNczogbnVtYmVyIHwgdW5kZWZpbmVkLFxuKTogKCkgPT4gdm9pZCB7XG4gIGlmIChzdGFsZU1zID09PSB1bmRlZmluZWQpIHJldHVybiAoKSA9PiB7fTtcbiAgY29uc3QgaW50ZXJ2YWxNcyA9IHVwZGF0ZU1zID8/IE1hdGgubWF4KDEsIE1hdGguZmxvb3Ioc3RhbGVNcyAvIDIpKTtcbiAgY29uc3QgdGltZXIgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgY29uc3Qgbm93ID0gbmV3IERhdGUoKTtcbiAgICB2b2lkIHV0aW1lcyhsb2NrUGF0aCwgbm93LCBub3cpLmNhdGNoKChjYXVzZSkgPT4ge1xuICAgICAgbG9nZ2VyLndhcm4oXCJmaWxlIGxvY2sgaGVhcnRiZWF0IGZhaWxlZFwiLCB7XG4gICAgICAgIHBhdGg6IGxvY2tQYXRoLFxuICAgICAgICBlcnJvcjogZXJyb3IuZXJyb3JNZXNzYWdlKGNhdXNlKSxcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9LCBpbnRlcnZhbE1zKTtcbiAgdGltZXIudW5yZWYoKTtcbiAgcmV0dXJuICgpID0+IGNsZWFySW50ZXJ2YWwodGltZXIpO1xufVxuXG5mdW5jdGlvbiBhc3NlcnRCZWZvcmVEZWFkbGluZShsb2NrUGF0aDogc3RyaW5nLCBkZWFkbGluZTogbnVtYmVyIHwgdW5kZWZpbmVkKTogdm9pZCB7XG4gIGlmIChkZWFkbGluZSAhPT0gdW5kZWZpbmVkICYmIERhdGUubm93KCkgPj0gZGVhZGxpbmUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFRpbWVkIG91dCB3YWl0aW5nIGZvciBmaWxlIGxvY2s6ICR7bG9ja1BhdGh9YCk7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gZW5zdXJlUGFyZW50RGlyKGxvY2tQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgYXdhaXQgbWtkaXIoZGlybmFtZShsb2NrUGF0aCksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xufVxuIl19
|
|
236
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsZS1sb2NrLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2ZpbGUtbG9jay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBd0JHOzs7Ozs7Ozs7QUFFSCxPQUFPLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ2pFLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxTQUFTLENBQUM7QUFDakMsT0FBTyxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFMUMsT0FBTyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsY0FBYyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFFekYsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO0FBSzVDLE1BQU0sZ0JBQWdCLEdBQStCLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBRXZFLDJEQUEyRDtBQUMzRCxNQUFNLE9BQU8sR0FBRyxFQUFFLENBQUM7QUFFbkI7Ozs7R0FJRztBQUNILE1BQU0sUUFBUSxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLE1BQU0sQ0FBQztBQUUzRSwrRUFBK0U7QUFDL0UsTUFBTSxTQUFTLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLG1CQUFtQixDQUFDLElBQUksUUFBUSxHQUFHLENBQUMsQ0FBQztBQUVuRix1REFBdUQ7QUFDdkQsTUFBTSxPQUFPLEdBQUcsQ0FBQyxDQUFDO0FBQ2xCLE1BQU0sT0FBTyxHQUFHLENBQUMsQ0FBQztBQUNsQixNQUFNLE9BQU8sR0FBRyxDQUFDLENBQUM7QUFpQ2xCOzs7Ozs7Ozs7O0dBVUc7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLFlBQVksQ0FDaEMsR0FBWSxFQUNaLEVBQXdCLEVBQ3hCLFVBQTJCLEVBQUU7SUFFN0IsSUFBSSxPQUFPLENBQUMsU0FBUyxLQUFLLFNBQVMsSUFBSSxPQUFPLENBQUMsU0FBUyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQzdELE1BQU0sSUFBSSxTQUFTLENBQUMsZ0NBQWdDLENBQUMsQ0FBQztJQUN4RCxDQUFDO0lBQ0QsTUFBTSxFQUFFLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3ZCLE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxRQUFRLElBQUksZ0JBQWdCLENBQUM7SUFDdEQsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztJQUM3RCxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsU0FBUyxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQztJQUU5RixLQUFLLE1BQU0sT0FBTyxJQUFJLFFBQVEsRUFBRSxDQUFDO1FBQy9CLFFBQVEsT0FBTyxFQUFFLENBQUM7WUFDaEIsS0FBSyxPQUFPLENBQUMsQ0FBQyxDQUFDO2dCQUNiLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLFFBQVEsQ0FBQyxDQUFDO2dCQUMxQyxNQUFNLEtBQUssR0FBRyxNQUFNLFlBQVksRUFBRSxDQUFDO2dCQUNuQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7b0JBQ1gsTUFBTSxDQUFDLEtBQUssQ0FBQywwQkFBMEIsRUFBRSxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztvQkFDL0QsU0FBUztnQkFDWCxDQUFDO2dCQUNELE1BQU0sQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLEVBQUUsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztnQkFDckUsT0FBTyxDQUFDLFNBQVMsRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztnQkFDakMsT0FBTyxTQUFTLENBQUMsUUFBUSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDbEQsQ0FBQztZQUNELEtBQUssTUFBTSxDQUFDLENBQUMsQ0FBQztnQkFDWixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxPQUFPLENBQUMsQ0FBQztnQkFDekMsTUFBTSxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsRUFBRSxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO2dCQUNyRSxPQUFPLENBQUMsU0FBUyxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO2dCQUNqQyxPQUFPLGlCQUFpQixDQUFDLFFBQVEsRUFBRSxRQUFRLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDbkQsQ0FBQztZQUNELE9BQU8sQ0FBQyxDQUFDLENBQUM7Z0JBQ1IsTUFBTSxXQUFXLEdBQVUsT0FBTyxDQUFDO2dCQUNuQyxNQUFNLElBQUksS0FBSyxDQUFDLDhCQUE4QixNQUFNLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ3ZFLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVELE1BQU0sSUFBSSxLQUFLLENBQUMseUNBQXlDLENBQUMsQ0FBQztBQUM3RCxDQUFDO0FBRUQsbURBQW1EO0FBQ25ELFNBQVMsTUFBTSxDQUFDLEdBQVk7SUFDMUIsTUFBTSxNQUFNLEdBQUcsTUFBTTtTQUNsQixXQUFXLENBQUMsR0FBRyxDQUFDO1NBQ2hCLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUN2QyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDbEIsOEVBQThFO0lBQzlFLGlFQUFpRTtJQUNqRSxPQUFPLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDOUIsQ0FBQztBQUVEOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLFlBQVksR0FBRyxjQUFjLENBQUMsT0FBTyxDQUFDLEtBQUssSUFBa0MsRUFBRTtJQUNuRixJQUFJLE9BQU8sQ0FBQyxRQUFRLEtBQUssT0FBTztRQUFFLE9BQU8sU0FBUyxDQUFDO0lBQ25ELElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLEdBQUc7UUFBRSxPQUFPLFNBQVMsQ0FBQztJQUU1QyxJQUFJLENBQUM7UUFDSCw4RUFBOEU7UUFDOUUsaURBQWlEO1FBQ2pELE1BQU0sU0FBUyxHQUFHLFNBQVMsQ0FBQztRQUM1QixNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sTUFBTSxrQ0FBQyxTQUFTLEVBQUMsQ0FBNEIsQ0FBQztRQUNqRSxNQUFNLE9BQU8sR0FDWCxPQUFPLENBQUMsUUFBUSxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxDQUFDLFFBQVEsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQzdFLE1BQU0sR0FBRyxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFO1lBQzlCLEtBQUssRUFBRSxFQUFFLElBQUksRUFBRSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFO1NBQ2hELENBQUMsQ0FBQztRQUNILE9BQU8sR0FBRyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUM7SUFDM0IsQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixNQUFNLENBQUMsS0FBSyxDQUFDLHVCQUF1QixFQUFFLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQzVFLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7QUFDSCxDQUFDLENBQUMsQ0FBQztBQUVILEtBQUssVUFBVSxTQUFTLENBQ3RCLFFBQWdCLEVBQ2hCLEtBQWMsRUFDZCxRQUE0QixFQUM1QixFQUF3QjtJQUV4QixNQUFNLGVBQWUsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNoQyxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDMUMsSUFBSSxDQUFDO1FBQ0gsTUFBTSxZQUFZLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1FBQ3pELElBQUksQ0FBQztZQUNILE9BQU8sTUFBTSxFQUFFLEVBQUUsQ0FBQztRQUNwQixDQUFDO2dCQUFTLENBQUM7WUFDVCxLQUFLLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUM1QixDQUFDO0lBQ0gsQ0FBQztZQUFTLENBQUM7UUFDVCxNQUFNLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDeEMsQ0FBQztBQUNILENBQUM7QUFFRCxLQUFLLFVBQVUsWUFBWSxDQUN6QixFQUFVLEVBQ1YsS0FBYyxFQUNkLFFBQWdCLEVBQ2hCLFFBQTRCO0lBRTVCLFNBQVUsQ0FBQztRQUNULE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxFQUFFLEVBQUUsT0FBTyxHQUFHLE9BQU8sQ0FBQyxDQUFDO1FBQ3hDLElBQUksRUFBRSxLQUFLLENBQUM7WUFBRSxPQUFPO1FBQ3JCLG9CQUFvQixDQUFDLFFBQVEsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUN6QyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDN0IsQ0FBQztBQUNILENBQUM7QUFFRDs7Ozs7OztHQU9HO0FBQ0gsS0FBSyxVQUFVLGlCQUFpQixDQUM5QixRQUFnQixFQUNoQixRQUE0QixFQUM1QixFQUF3QjtJQUV4QixNQUFNLGVBQWUsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNoQyxNQUFNLG9CQUFvQixDQUFDLFFBQVEsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUMvQyxNQUFNLGFBQWEsR0FBRyxjQUFjLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDL0MsSUFBSSxDQUFDO1FBQ0gsT0FBTyxNQUFNLEVBQUUsRUFBRSxDQUFDO0lBQ3BCLENBQUM7WUFBUyxDQUFDO1FBQ1QsYUFBYSxFQUFFLENBQUM7UUFDaEIsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDeEUsQ0FBQztBQUNILENBQUM7QUFFRCxLQUFLLFVBQVUsb0JBQW9CLENBQ2pDLFFBQWdCLEVBQ2hCLFFBQTRCO0lBRTVCLFNBQVUsQ0FBQztRQUNULElBQUksQ0FBQztZQUNILE1BQU0sS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ3RCLE9BQU87UUFDVCxDQUFDO1FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztZQUNmLE1BQU0sR0FBRyxHQUFHLEtBQThCLENBQUM7WUFDM0MsSUFBSSxHQUFHLENBQUMsSUFBSSxLQUFLLFFBQVE7Z0JBQUUsTUFBTSxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3RELE1BQU0saUJBQWlCLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDbEMsb0JBQW9CLENBQUMsUUFBUSxFQUFFLFFBQVEsQ0FBQyxDQUFDO1lBQ3pDLE1BQU0sS0FBSyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUM3QixDQUFDO0lBQ0gsQ0FBQztBQUNILENBQUM7QUFFRCxLQUFLLFVBQVUsaUJBQWlCLENBQUMsUUFBZ0I7SUFDL0MsSUFBSSxDQUFDO1FBQ0gsTUFBTSxFQUFFLE9BQU8sRUFBRSxHQUFHLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3pDLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxPQUFPLENBQUM7UUFDakMsSUFBSSxHQUFHLEdBQUcsUUFBUTtZQUFFLE9BQU87UUFDM0IsTUFBTSxDQUFDLEtBQUssQ0FBQyxpQ0FBaUMsRUFBRSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDaEYsTUFBTSxFQUFFLENBQUMsUUFBUSxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUN2RCxDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLE1BQU0sR0FBRyxHQUFHLEtBQThCLENBQUM7UUFDM0MsSUFBSSxHQUFHLENBQUMsSUFBSSxLQUFLLFFBQVE7WUFBRSxNQUFNLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDeEQsQ0FBQztBQUNILENBQUM7QUFFRCxTQUFTLGNBQWMsQ0FBQyxRQUFnQjtJQUN0QyxNQUFNLEtBQUssR0FBRyxXQUFXLENBQUMsR0FBRyxFQUFFO1FBQzdCLE1BQU0sR0FBRyxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7UUFDdkIsS0FBSyxNQUFNLENBQUMsUUFBUSxFQUFFLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRTtZQUM5QyxNQUFNLENBQUMsSUFBSSxDQUFDLDRCQUE0QixFQUFFO2dCQUN4QyxJQUFJLEVBQUUsUUFBUTtnQkFDZCxLQUFLLEVBQUUsS0FBSyxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUM7YUFDakMsQ0FBQyxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDZCxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDZCxPQUFPLEdBQUcsRUFBRSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUNwQyxDQUFDO0FBRUQsU0FBUyxvQkFBb0IsQ0FBQyxRQUFnQixFQUFFLFFBQTRCO0lBQzFFLElBQUksUUFBUSxLQUFLLFNBQVMsSUFBSSxJQUFJLENBQUMsR0FBRyxFQUFFLElBQUksUUFBUSxFQUFFLENBQUM7UUFDckQsTUFBTSxJQUFJLEtBQUssQ0FBQyxvQ0FBb0MsUUFBUSxFQUFFLENBQUMsQ0FBQztJQUNsRSxDQUFDO0FBQ0gsQ0FBQztBQUVELEtBQUssVUFBVSxlQUFlLENBQUMsUUFBZ0I7SUFDN0MsTUFBTSxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7QUFDdEQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ2FzY2FkaW5nIGNyb3NzLXByb2Nlc3MgbXV0dWFsIGV4Y2x1c2lvbiB2aWEgYSBsb2NrZmlsZS5cbiAqXG4gKiBTZXJpYWxpemVzIGNvbmN1cnJlbnQgKnByb2Nlc3NlcyogKHR3byBgYnVuIHJ1biBkZW1vYCBzaGVsbHMsIGEgQ0xJIGJlc2lkZSBhXG4gKiBzZXJ2ZXIpIG9uIHRoZSBzYW1lIGtleS4gRm9yIGluLXByb2Nlc3MgLyB3b3JrZXItdGhyZWFkIGV4Y2x1c2lvbiB1c2VcbiAqIHtAbGluayB3aXRoUHJvY2Vzc0xvY2t9IGZyb20gYC4vcHJvY2Vzcy1sb2NrLnRzYCBpbnN0ZWFkLlxuICpcbiAqIEJhY2tlbmRzLCBpbiBvcmRlcjpcbiAqXG4gKiAxLiAqKmZsb2NrKiog4oCUIGBmbG9jaygyKWAgdmlhIEJ1biBGRkkgb24gVW5peCB3aGVuIGBidW46ZmZpYCBjYW4gbG9hZCBsaWJjLlxuICogICAgTm90IGF2YWlsYWJsZSBvbiBXaW5kb3dzLCBhbmQgbm90IGF2YWlsYWJsZSB1bmRlciBwbGFpbiBOb2RlIChubyBGRkkpLlxuICogICAgS2VybmVsIHJlbGVhc2VzIHRoZSBsb2NrIHdoZW4gdGhlIGZkIGNsb3NlcyAoaW5jbHVkaW5nIHByb2Nlc3MgZGVhdGgpLlxuICogMi4gKipmaWxlKiog4oCUIGF0b21pYyBsb2NrLWRpcmVjdG9yeSBjcmVhdGlvbi4gVGhpcyBpcyB0aGUgc3RyYXRlZ3kgdXNlZCBieVxuICogICAgYHByb3Blci1sb2NrZmlsZWA6IGBta2RpcmAgaXMgYXRvbWljIG9uIFdpbmRvd3MsIFVuaXgsIGFuZCBuZXR3b3JrIGZpbGVcbiAqICAgIHN5c3RlbXMgd2hlcmUgYG9wZW4oLi4uLCBcInd4XCIpYCBtYXkgbm90IGJlIHJlbGlhYmxlLiBTdGFsZSBkZXRlY3Rpb24gaXNcbiAqICAgIGFsd2F5cyBvbiAoZml4ZWQge0BsaW5rIFNUQUxFX01TfSArIGhlYXJ0YmVhdCkgc28gYSBjcmFzaGVkIGhvbGRlciBvbiB0aGlzXG4gKiAgICBiYWNrZW5kIGNhbiBiZSByZWNsYWltZWQuXG4gKlxuICogVGhlIGZpcnN0IGJhY2tlbmQgdGhhdCBjYW4gYmUgKmluaXRpYWxpemVkKiBpcyB1c2VkIGZvciB0aGUgd2hvbGUgY2FsbC4gQSBidXN5XG4gKiBsb2NrIHdhaXRzOyBhbiB1bmF2YWlsYWJsZSBiYWNrZW5kIGZhbGxzIHRocm91Z2ggdG8gdGhlIG5leHQuIENhbGxlcnMgbWF5IG9ubHlcbiAqIGJvdW5kIGhvdyBsb25nIHRvIHdhaXQgKHtAbGluayBGaWxlTG9ja09wdGlvbnMudGltZW91dE1zfSk7IHN0YWxlIHRpbWluZyBpc1xuICogbm90IGNvbmZpZ3VyYWJsZSBzbyBldmVyeSBob2xkZXIgYW5kIHdhaXRlciBhZ3JlZXMuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IG1rZGlyLCBvcGVuLCBybSwgc3RhdCwgdXRpbWVzIH0gZnJvbSBcIm5vZGU6ZnMvcHJvbWlzZXNcIjtcbmltcG9ydCB7IHRtcGRpciB9IGZyb20gXCJub2RlOm9zXCI7XG5pbXBvcnQgeyBkaXJuYW1lLCBqb2luIH0gZnJvbSBcIm5vZGU6cGF0aFwiO1xuXG5pbXBvcnQgeyBhc3luYywgZXJyb3IsIGZ1bmN0aW9uTW9kdWxlLCBoYXNoLCBsb2csIG9iamVjdCB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGxvZy5sb2dnZXIoXCJjb3JlOmZpbGUtbG9ja1wiKTtcblxuLyoqIEJhY2tlbmRzIHtAbGluayB3aXRoRmlsZUxvY2t9IGNhbiBhdHRlbXB0LCBpbiBjYXNjYWRlIG9yZGVyLiAqL1xuZXhwb3J0IHR5cGUgRmlsZUxvY2tCYWNrZW5kID0gXCJmbG9ja1wiIHwgXCJmaWxlXCI7XG5cbmNvbnN0IERFRkFVTFRfQkFDS0VORFM6IHJlYWRvbmx5IEZpbGVMb2NrQmFja2VuZFtdID0gW1wiZmxvY2tcIiwgXCJmaWxlXCJdO1xuXG4vKiogUG9sbCBpbnRlcnZhbCB3aGlsZSB3YWl0aW5nIGZvciBhIGNvbnRlbmRlZCBPUyBsb2NrLiAqL1xuY29uc3QgUE9MTF9NUyA9IDUwO1xuXG4vKipcbiAqIEFnZSBhZnRlciB3aGljaCBhbiB1bnJlZnJlc2hlZCBsb2NrIGRpcmVjdG9yeSBtYXkgYmUgcmVtb3ZlZC5cbiAqIE1hdGNoZXMgYHByb3Blci1sb2NrZmlsZWAncyBkZWZhdWx0LiBOb3QgY2FsbGVyLWNvbmZpZ3VyYWJsZTogZXZlcnkgcHJvY2Vzc1xuICogbXVzdCBzaGFyZSB0aGUgc2FtZSB0aHJlc2hvbGQgb3IgYSBsaXZlIGhvbGRlciBjYW4gYmUgbWlzdGFrZW4gZm9yIHN0YWxlLlxuICovXG5jb25zdCBTVEFMRV9NUyA9IG9iamVjdC50b051bWJlcihwcm9jZXNzLmVudi5GSUxFX0xPQ0tfU1RBTEVfTVMpID8/IDEwXzAwMDtcblxuLyoqIEhlYXJ0YmVhdCBpbnRlcnZhbCBmb3IgcmVmcmVzaGluZyBsb2NrLWRpcmVjdG9yeSBtdGltZSAoYFNUQUxFX01TIC8gMmApLiAqL1xuY29uc3QgVVBEQVRFX01TID0gb2JqZWN0LnRvTnVtYmVyKHByb2Nlc3MuZW52LkZJTEVfTE9DS19VUERBVEVfTVMpID8/IFNUQUxFX01TIC8gMjtcblxuLyoqIGBmbG9jaygyKWAgb3BlcmF0aW9uIGJpdHMgKExpbnV4IC8gbWFjT1MgLyBCU0QpLiAqL1xuY29uc3QgTE9DS19FWCA9IDI7XG5jb25zdCBMT0NLX05CID0gNDtcbmNvbnN0IExPQ0tfVU4gPSA4O1xuXG4vKiogUmVzdWx0IG1ldGFkYXRhIHdoZW4gYSBjYWxsZXIgd2FudHMgdG8ga25vdyB3aGljaCBiYWNrZW5kIHJhbi4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRmlsZUxvY2tBY3F1aXNpdGlvbiB7XG4gIGJhY2tlbmQ6IEZpbGVMb2NrQmFja2VuZDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBGaWxlTG9ja09wdGlvbnMge1xuICAvKipcbiAgICogRGlyZWN0b3J5IGZvciBsb2NrZmlsZXMuIERlZmF1bHRzIHRvIGAkVE1QRElSL2RieC10b29scy1sb2Nrc2AuXG4gICAqL1xuICBkaXI/OiBzdHJpbmc7XG4gIC8qKiBPdmVycmlkZSB0aGUgY2FzY2FkZS4gRGVmYXVsdHMgdG8gYGZsb2NrYCDihpIgYGZpbGVgLiAqL1xuICBiYWNrZW5kcz86IHJlYWRvbmx5IEZpbGVMb2NrQmFja2VuZFtdO1xuICAvKipcbiAgICogU3RvcCB3YWl0aW5nIGFuZCB0aHJvdyBhZnRlciB0aGlzIG1hbnkgbWlsbGlzZWNvbmRzLiBPbWl0IHRvIHBvbGwgZm9yZXZlci5cbiAgICogVGhpcyBpcyB0aGUgb25seSB3YWl0LWxvb3Aga25vYjsgc3RhbGUgcmVjbGFpbSB0aW1pbmcgaXMgZml4ZWQuXG4gICAqL1xuICB0aW1lb3V0TXM/OiBudW1iZXI7XG4gIC8qKiBJbnZva2VkIG9uY2UgdGhlIGJhY2tlbmQgZm9yIHRoaXMgY2FsbCBoYXMgYmVlbiBjaG9zZW4uICovXG4gIG9uQWNxdWlyZT86IChhY3F1aXNpdGlvbjogRmlsZUxvY2tBY3F1aXNpdGlvbikgPT4gdm9pZDtcbn1cblxudHlwZSBGbG9ja0ZuID0gKGZkOiBudW1iZXIsIG9wZXJhdGlvbjogbnVtYmVyKSA9PiBudW1iZXI7XG5cbmludGVyZmFjZSBCdW5GZmlNb2R1bGUge1xuICBkbG9wZW46IChcbiAgICBwYXRoOiBzdHJpbmcsXG4gICAgc3ltYm9sczogUmVjb3JkPHN0cmluZywgeyBhcmdzOiBzdHJpbmdbXTsgcmV0dXJuczogc3RyaW5nIH0+LFxuICApID0+IHsgc3ltYm9sczogeyBmbG9jazogRmxvY2tGbiB9IH07XG4gIHN1ZmZpeDogc3RyaW5nO1xufVxuXG4vKipcbiAqIFJ1biBgZm5gIHdoaWxlIGhvbGRpbmcgYSBjcm9zcy1wcm9jZXNzIGxvY2sgbmFtZWQgYnkgYGtleWAuXG4gKlxuICogYGtleWAgaXMgY2Fub25pY2FsaXplZCB3aXRoIGBvYmplY3QudG9TdGFibGVLZXlgLCB0aGUgc2FtZSBpZGVudGl0eSBydWxlIGFzXG4gKiBwcm9jZXNzIGFuZCBQb3N0Z3JlcyBhZHZpc29yeSBsb2Nrcy5cbiAqXG4gKiBAZXhhbXBsZVxuICogYXdhaXQgd2l0aEZpbGVMb2NrKFtcImNhY2hlXCIsIFwiYXBwa2l0XCJdLCBhc3luYyAoKSA9PiB7XG4gKiAgIGF3YWl0IG1pZ3JhdGUoKTtcbiAqIH0pO1xuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd2l0aEZpbGVMb2NrPFQ+KFxuICBrZXk6IHVua25vd24sXG4gIGZuOiAoKSA9PiBUIHwgUHJvbWlzZTxUPixcbiAgb3B0aW9uczogRmlsZUxvY2tPcHRpb25zID0ge30sXG4pOiBQcm9taXNlPFQ+IHtcbiAgaWYgKG9wdGlvbnMudGltZW91dE1zICE9PSB1bmRlZmluZWQgJiYgb3B0aW9ucy50aW1lb3V0TXMgPCAwKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcInRpbWVvdXRNcyBtdXN0IGJlIG5vbi1uZWdhdGl2ZVwiKTtcbiAgfVxuICBjb25zdCBpZCA9IGxvY2tJZChrZXkpO1xuICBjb25zdCBiYWNrZW5kcyA9IG9wdGlvbnMuYmFja2VuZHMgPz8gREVGQVVMVF9CQUNLRU5EUztcbiAgY29uc3QgZGlyID0gb3B0aW9ucy5kaXIgPz8gam9pbih0bXBkaXIoKSwgXCJkYngtdG9vbHMtbG9ja3NcIik7XG4gIGNvbnN0IGRlYWRsaW5lID0gb3B0aW9ucy50aW1lb3V0TXMgPT09IHVuZGVmaW5lZCA/IHVuZGVmaW5lZCA6IERhdGUubm93KCkgKyBvcHRpb25zLnRpbWVvdXRNcztcblxuICBmb3IgKGNvbnN0IGJhY2tlbmQgb2YgYmFja2VuZHMpIHtcbiAgICBzd2l0Y2ggKGJhY2tlbmQpIHtcbiAgICAgIGNhc2UgXCJmbG9ja1wiOiB7XG4gICAgICAgIGNvbnN0IGxvY2tQYXRoID0gam9pbihkaXIsIGAke2lkfS5mbG9ja2ApO1xuICAgICAgICBjb25zdCBmbG9jayA9IGF3YWl0IHJlc29sdmVGbG9jaygpO1xuICAgICAgICBpZiAoIWZsb2NrKSB7XG4gICAgICAgICAgbG9nZ2VyLmRlYnVnKFwibG9jayBiYWNrZW5kIHVuYXZhaWxhYmxlXCIsIHsgYmFja2VuZCwga2V5OiBpZCB9KTtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBsb2dnZXIuZGVidWcoXCJhY3F1aXJpbmcgbG9ja1wiLCB7IGJhY2tlbmQsIGtleTogaWQsIHBhdGg6IGxvY2tQYXRoIH0pO1xuICAgICAgICBvcHRpb25zLm9uQWNxdWlyZT8uKHsgYmFja2VuZCB9KTtcbiAgICAgICAgcmV0dXJuIGhvbGRGbG9jayhsb2NrUGF0aCwgZmxvY2ssIGRlYWRsaW5lLCBmbik7XG4gICAgICB9XG4gICAgICBjYXNlIFwiZmlsZVwiOiB7XG4gICAgICAgIGNvbnN0IGxvY2tQYXRoID0gam9pbihkaXIsIGAke2lkfS5sb2NrYCk7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZyhcImFjcXVpcmluZyBsb2NrXCIsIHsgYmFja2VuZCwga2V5OiBpZCwgcGF0aDogbG9ja1BhdGggfSk7XG4gICAgICAgIG9wdGlvbnMub25BY3F1aXJlPy4oeyBiYWNrZW5kIH0pO1xuICAgICAgICByZXR1cm4gaG9sZExvY2tEaXJlY3RvcnkobG9ja1BhdGgsIGRlYWRsaW5lLCBmbik7XG4gICAgICB9XG4gICAgICBkZWZhdWx0OiB7XG4gICAgICAgIGNvbnN0IF9leGhhdXN0aXZlOiBuZXZlciA9IGJhY2tlbmQ7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgdW5rbm93biBmaWxlLWxvY2sgYmFja2VuZDogJHtTdHJpbmcoX2V4aGF1c3RpdmUpfWApO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihcIndpdGhGaWxlTG9jazogbm8gbG9jayBiYWNrZW5kIGF2YWlsYWJsZVwiKTtcbn1cblxuLyoqIENhbm9uaWNhbCBmaWxlc3lzdGVtLXNhZmUgaWQgZm9yIGEgbG9jayBrZXkuICovXG5mdW5jdGlvbiBsb2NrSWQoa2V5OiB1bmtub3duKTogc3RyaW5nIHtcbiAgY29uc3Qgc3RhYmxlID0gb2JqZWN0XG4gICAgLnRvT25lT3JNYW55KGtleSlcbiAgICAubWFwKChwYXJ0KSA9PiBvYmplY3QudG9TdGFibGVLZXkocGFydCkpXG4gICAgLmpvaW4oXCJcXHUwMDAwXCIpO1xuICAvLyBTaG9ydCBkaWdlc3Qgc28gcGF0aHMgc3RheSB3ZWxsIHVuZGVyIE9TIGxpbWl0czsgY29sbGlzaW9ucyBhcmUgZmluZSDigJQgdGhleVxuICAvLyBvbmx5IG1lcmdlIGNyaXRpY2FsIHNlY3Rpb25zIHRoYXQgYWxyZWFkeSBzaGFyZWQgYSBrZXkgc3RyaW5nLlxuICByZXR1cm4gaGFzaC5mbnZIYXNoKHN0YWJsZSk7XG59XG5cbi8qKlxuICogUmVzb2x2ZSBgZmxvY2soMilgIHRocm91Z2ggQnVuIEZGSSB3aGVuIHBvc3NpYmxlLlxuICpcbiAqIE1lbW9pemVkOiB0aGUgRkZJIGltcG9ydCArIGxpYmMgYGRsb3BlbmAgcnVuIG9uY2UgcGVyIHByb2Nlc3MuIFJldHVybnNcbiAqIGB1bmRlZmluZWRgIG9uIFdpbmRvd3MsIHVuZGVyIHBsYWluIE5vZGUsIG9yIHdoZW4gbGliYyBjYW5ub3QgYmUgbG9hZGVkIOKAlFxuICogY2FsbGVycyBmYWxsIHRocm91Z2ggdG8gdGhlIG5leHQgYmFja2VuZC4gQSBtaXNzIGlzIGNhY2hlZCB0b28sIHNvIGEgcHJvY2Vzc1xuICogdGhhdCBjYW5ub3QgZmxvY2sgbmV2ZXIgcmV0cmllcyB0aGUgbG9hZC5cbiAqL1xuY29uc3QgcmVzb2x2ZUZsb2NrID0gZnVuY3Rpb25Nb2R1bGUubWVtb2l6ZShhc3luYyAoKTogUHJvbWlzZTxGbG9ja0ZuIHwgdW5kZWZpbmVkPiA9PiB7XG4gIGlmIChwcm9jZXNzLnBsYXRmb3JtID09PSBcIndpbjMyXCIpIHJldHVybiB1bmRlZmluZWQ7XG4gIGlmICghcHJvY2Vzcy52ZXJzaW9ucy5idW4pIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgdHJ5IHtcbiAgICAvLyBEeW5hbWljIHNwZWNpZmllciBzbyBgdHNjYCAobm8gYEB0eXBlc2AgZm9yIGBidW46ZmZpYCkgZG9lcyBub3QgcmVzb2x2ZSBpdDtcbiAgICAvLyB0aGUgaW1wb3J0IG9ubHkgc3VjY2VlZHMgdW5kZXIgQnVuIGF0IHJ1bnRpbWUuXG4gICAgY29uc3Qgc3BlY2lmaWVyID0gXCJidW46ZmZpXCI7XG4gICAgY29uc3QgZmZpID0gKGF3YWl0IGltcG9ydChzcGVjaWZpZXIpKSBhcyB1bmtub3duIGFzIEJ1bkZmaU1vZHVsZTtcbiAgICBjb25zdCBsaWJQYXRoID1cbiAgICAgIHByb2Nlc3MucGxhdGZvcm0gPT09IFwiZGFyd2luXCIgPyBcImxpYlN5c3RlbS5CLmR5bGliXCIgOiBgbGliYy4ke2ZmaS5zdWZmaXh9YDtcbiAgICBjb25zdCBsaWIgPSBmZmkuZGxvcGVuKGxpYlBhdGgsIHtcbiAgICAgIGZsb2NrOiB7IGFyZ3M6IFtcImkzMlwiLCBcImkzMlwiXSwgcmV0dXJuczogXCJpMzJcIiB9LFxuICAgIH0pO1xuICAgIHJldHVybiBsaWIuc3ltYm9scy5mbG9jaztcbiAgfSBjYXRjaCAoY2F1c2UpIHtcbiAgICBsb2dnZXIuZGVidWcoXCJmbG9jayBGRkkgdW5hdmFpbGFibGVcIiwgeyBlcnJvcjogZXJyb3IuZXJyb3JNZXNzYWdlKGNhdXNlKSB9KTtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59KTtcblxuYXN5bmMgZnVuY3Rpb24gaG9sZEZsb2NrPFQ+KFxuICBsb2NrUGF0aDogc3RyaW5nLFxuICBmbG9jazogRmxvY2tGbixcbiAgZGVhZGxpbmU6IG51bWJlciB8IHVuZGVmaW5lZCxcbiAgZm46ICgpID0+IFQgfCBQcm9taXNlPFQ+LFxuKTogUHJvbWlzZTxUPiB7XG4gIGF3YWl0IGVuc3VyZVBhcmVudERpcihsb2NrUGF0aCk7XG4gIGNvbnN0IGhhbmRsZSA9IGF3YWl0IG9wZW4obG9ja1BhdGgsIFwiYStcIik7XG4gIHRyeSB7XG4gICAgYXdhaXQgd2FpdEZvckZsb2NrKGhhbmRsZS5mZCwgZmxvY2ssIGxvY2tQYXRoLCBkZWFkbGluZSk7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBhd2FpdCBmbigpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBmbG9jayhoYW5kbGUuZmQsIExPQ0tfVU4pO1xuICAgIH1cbiAgfSBmaW5hbGx5IHtcbiAgICBhd2FpdCBoYW5kbGUuY2xvc2UoKS5jYXRjaCgoKSA9PiB7IH0pO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHdhaXRGb3JGbG9jayhcbiAgZmQ6IG51bWJlcixcbiAgZmxvY2s6IEZsb2NrRm4sXG4gIGxvY2tQYXRoOiBzdHJpbmcsXG4gIGRlYWRsaW5lOiBudW1iZXIgfCB1bmRlZmluZWQsXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgZm9yICg7IDspIHtcbiAgICBjb25zdCByYyA9IGZsb2NrKGZkLCBMT0NLX0VYIHwgTE9DS19OQik7XG4gICAgaWYgKHJjID09PSAwKSByZXR1cm47XG4gICAgYXNzZXJ0QmVmb3JlRGVhZGxpbmUobG9ja1BhdGgsIGRlYWRsaW5lKTtcbiAgICBhd2FpdCBhc3luYy5zbGVlcChQT0xMX01TKTtcbiAgfVxufVxuXG4vKipcbiAqIEF0b21pYyBsb2NrLWRpcmVjdG9yeSBjcmVhdGlvbiDigJQgdGhlIHBvcnRhYmxlIC8gV2luZG93cyBwYXRoLlxuICpcbiAqIGBta2RpcmAgaXMgdGhlIHNhbWUgcHJpbWl0aXZlIHVzZWQgYnkgYHByb3Blci1sb2NrZmlsZWA6IGl0IGlzIGF0b21pYyBhY3Jvc3NcbiAqIHN1cHBvcnRlZCBsb2NhbCBhbmQgbmV0d29yayBmaWxlc3lzdGVtcy4gVGhlIGhvbGRlciByZWZyZXNoZXMgbXRpbWUgb24gYSBmaXhlZFxuICogaGVhcnRiZWF0IHNvIGEgbGl2ZSBsb25nLXJ1bm5pbmcgbG9jayBpcyBuZXZlciByZWNsYWltZWQ7IGEgY3Jhc2hlZCBob2xkZXInc1xuICogZGlyZWN0b3J5IGJlY29tZXMgcmVjbGFpbWFibGUgYWZ0ZXIge0BsaW5rIFNUQUxFX01TfS5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gaG9sZExvY2tEaXJlY3Rvcnk8VD4oXG4gIGxvY2tQYXRoOiBzdHJpbmcsXG4gIGRlYWRsaW5lOiBudW1iZXIgfCB1bmRlZmluZWQsXG4gIGZuOiAoKSA9PiBUIHwgUHJvbWlzZTxUPixcbik6IFByb21pc2U8VD4ge1xuICBhd2FpdCBlbnN1cmVQYXJlbnREaXIobG9ja1BhdGgpO1xuICBhd2FpdCBhY3F1aXJlTG9ja0RpcmVjdG9yeShsb2NrUGF0aCwgZGVhZGxpbmUpO1xuICBjb25zdCBzdG9wSGVhcnRiZWF0ID0gc3RhcnRIZWFydGJlYXQobG9ja1BhdGgpO1xuICB0cnkge1xuICAgIHJldHVybiBhd2FpdCBmbigpO1xuICB9IGZpbmFsbHkge1xuICAgIHN0b3BIZWFydGJlYXQoKTtcbiAgICBhd2FpdCBybShsb2NrUGF0aCwgeyByZWN1cnNpdmU6IHRydWUsIGZvcmNlOiB0cnVlIH0pLmNhdGNoKCgpID0+IHsgfSk7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gYWNxdWlyZUxvY2tEaXJlY3RvcnkoXG4gIGxvY2tQYXRoOiBzdHJpbmcsXG4gIGRlYWRsaW5lOiBudW1iZXIgfCB1bmRlZmluZWQsXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgZm9yICg7IDspIHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgbWtkaXIobG9ja1BhdGgpO1xuICAgICAgcmV0dXJuO1xuICAgIH0gY2F0Y2ggKGNhdXNlKSB7XG4gICAgICBjb25zdCBlcnIgPSBjYXVzZSBhcyBOb2RlSlMuRXJybm9FeGNlcHRpb247XG4gICAgICBpZiAoZXJyLmNvZGUgIT09IFwiRUVYSVNUXCIpIHRocm93IGVycm9yLnRvRXJyb3IoY2F1c2UpO1xuICAgICAgYXdhaXQgbWF5YmVSZWNsYWltU3RhbGUobG9ja1BhdGgpO1xuICAgICAgYXNzZXJ0QmVmb3JlRGVhZGxpbmUobG9ja1BhdGgsIGRlYWRsaW5lKTtcbiAgICAgIGF3YWl0IGFzeW5jLnNsZWVwKFBPTExfTVMpO1xuICAgIH1cbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiBtYXliZVJlY2xhaW1TdGFsZShsb2NrUGF0aDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gIHRyeSB7XG4gICAgY29uc3QgeyBtdGltZU1zIH0gPSBhd2FpdCBzdGF0KGxvY2tQYXRoKTtcbiAgICBjb25zdCBhZ2UgPSBEYXRlLm5vdygpIC0gbXRpbWVNcztcbiAgICBpZiAoYWdlIDwgU1RBTEVfTVMpIHJldHVybjtcbiAgICBsb2dnZXIuZGVidWcoXCJyZWNsYWltaW5nIHN0YWxlIGxvY2sgZGlyZWN0b3J5XCIsIHsgcGF0aDogbG9ja1BhdGgsIGFnZU1zOiBhZ2UgfSk7XG4gICAgYXdhaXQgcm0obG9ja1BhdGgsIHsgcmVjdXJzaXZlOiB0cnVlLCBmb3JjZTogdHJ1ZSB9KTtcbiAgfSBjYXRjaCAoY2F1c2UpIHtcbiAgICBjb25zdCBlcnIgPSBjYXVzZSBhcyBOb2RlSlMuRXJybm9FeGNlcHRpb247XG4gICAgaWYgKGVyci5jb2RlICE9PSBcIkVOT0VOVFwiKSB0aHJvdyBlcnJvci50b0Vycm9yKGNhdXNlKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBzdGFydEhlYXJ0YmVhdChsb2NrUGF0aDogc3RyaW5nKTogKCkgPT4gdm9pZCB7XG4gIGNvbnN0IHRpbWVyID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgIGNvbnN0IG5vdyA9IG5ldyBEYXRlKCk7XG4gICAgdm9pZCB1dGltZXMobG9ja1BhdGgsIG5vdywgbm93KS5jYXRjaCgoY2F1c2UpID0+IHtcbiAgICAgIGxvZ2dlci53YXJuKFwiZmlsZSBsb2NrIGhlYXJ0YmVhdCBmYWlsZWRcIiwge1xuICAgICAgICBwYXRoOiBsb2NrUGF0aCxcbiAgICAgICAgZXJyb3I6IGVycm9yLmVycm9yTWVzc2FnZShjYXVzZSksXG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSwgVVBEQVRFX01TKTtcbiAgdGltZXIudW5yZWYoKTtcbiAgcmV0dXJuICgpID0+IGNsZWFySW50ZXJ2YWwodGltZXIpO1xufVxuXG5mdW5jdGlvbiBhc3NlcnRCZWZvcmVEZWFkbGluZShsb2NrUGF0aDogc3RyaW5nLCBkZWFkbGluZTogbnVtYmVyIHwgdW5kZWZpbmVkKTogdm9pZCB7XG4gIGlmIChkZWFkbGluZSAhPT0gdW5kZWZpbmVkICYmIERhdGUubm93KCkgPj0gZGVhZGxpbmUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFRpbWVkIG91dCB3YWl0aW5nIGZvciBmaWxlIGxvY2s6ICR7bG9ja1BhdGh9YCk7XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gZW5zdXJlUGFyZW50RGlyKGxvY2tQYXRoOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgYXdhaXQgbWtkaXIoZGlybmFtZShsb2NrUGF0aCksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xufVxuIl19
|
package/package.json
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"typescript": "^5.9.3"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@dbx-tools/shared-core": "0.6.
|
|
26
|
+
"@dbx-tools/shared-core": "0.6.72",
|
|
27
27
|
"extract-zip": "^2.0.1",
|
|
28
28
|
"tar": "^7.5.22",
|
|
29
29
|
"yaml": "^2.9.0"
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"./package.json": "./package.json"
|
|
43
43
|
}
|
|
44
44
|
},
|
|
45
|
-
"version": "0.6.
|
|
45
|
+
"version": "0.6.72",
|
|
46
46
|
"types": "./lib/index.d.ts",
|
|
47
47
|
"type": "module",
|
|
48
48
|
"exports": {
|
package/src/file-lock.ts
CHANGED
|
@@ -12,11 +12,14 @@
|
|
|
12
12
|
* Kernel releases the lock when the fd closes (including process death).
|
|
13
13
|
* 2. **file** — atomic lock-directory creation. This is the strategy used by
|
|
14
14
|
* `proper-lockfile`: `mkdir` is atomic on Windows, Unix, and network file
|
|
15
|
-
* systems where `open(..., "wx")` may not be reliable.
|
|
16
|
-
*
|
|
15
|
+
* systems where `open(..., "wx")` may not be reliable. Stale detection is
|
|
16
|
+
* always on (fixed {@link STALE_MS} + heartbeat) so a crashed holder on this
|
|
17
|
+
* backend can be reclaimed.
|
|
17
18
|
*
|
|
18
19
|
* The first backend that can be *initialized* is used for the whole call. A busy
|
|
19
|
-
* lock waits; an unavailable backend falls through to the next.
|
|
20
|
+
* lock waits; an unavailable backend falls through to the next. Callers may only
|
|
21
|
+
* bound how long to wait ({@link FileLockOptions.timeoutMs}); stale timing is
|
|
22
|
+
* not configurable so every holder and waiter agrees.
|
|
20
23
|
*
|
|
21
24
|
* @module
|
|
22
25
|
*/
|
|
@@ -37,6 +40,16 @@ const DEFAULT_BACKENDS: readonly FileLockBackend[] = ["flock", "file"];
|
|
|
37
40
|
/** Poll interval while waiting for a contended OS lock. */
|
|
38
41
|
const POLL_MS = 50;
|
|
39
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Age after which an unrefreshed lock directory may be removed.
|
|
45
|
+
* Matches `proper-lockfile`'s default. Not caller-configurable: every process
|
|
46
|
+
* must share the same threshold or a live holder can be mistaken for stale.
|
|
47
|
+
*/
|
|
48
|
+
const STALE_MS = object.toNumber(process.env.FILE_LOCK_STALE_MS) ?? 10_000;
|
|
49
|
+
|
|
50
|
+
/** Heartbeat interval for refreshing lock-directory mtime (`STALE_MS / 2`). */
|
|
51
|
+
const UPDATE_MS = object.toNumber(process.env.FILE_LOCK_UPDATE_MS) ?? STALE_MS / 2;
|
|
52
|
+
|
|
40
53
|
/** `flock(2)` operation bits (Linux / macOS / BSD). */
|
|
41
54
|
const LOCK_EX = 2;
|
|
42
55
|
const LOCK_NB = 4;
|
|
@@ -56,18 +69,9 @@ export interface FileLockOptions {
|
|
|
56
69
|
backends?: readonly FileLockBackend[];
|
|
57
70
|
/**
|
|
58
71
|
* Stop waiting and throw after this many milliseconds. Omit to poll forever.
|
|
72
|
+
* This is the only wait-loop knob; stale reclaim timing is fixed.
|
|
59
73
|
*/
|
|
60
74
|
timeoutMs?: number;
|
|
61
|
-
/**
|
|
62
|
-
* Age after which an unrefreshed lock directory may be removed. Omit to
|
|
63
|
-
* disable stale detection. Only used by the `file` backend.
|
|
64
|
-
*/
|
|
65
|
-
staleMs?: number;
|
|
66
|
-
/**
|
|
67
|
-
* Interval for refreshing the lock directory mtime when `staleMs` is set.
|
|
68
|
-
* Defaults to half of `staleMs`.
|
|
69
|
-
*/
|
|
70
|
-
updateMs?: number;
|
|
71
75
|
/** Invoked once the backend for this call has been chosen. */
|
|
72
76
|
onAcquire?: (acquisition: FileLockAcquisition) => void;
|
|
73
77
|
}
|
|
@@ -98,7 +102,9 @@ export async function withFileLock<T>(
|
|
|
98
102
|
fn: () => T | Promise<T>,
|
|
99
103
|
options: FileLockOptions = {},
|
|
100
104
|
): Promise<T> {
|
|
101
|
-
|
|
105
|
+
if (options.timeoutMs !== undefined && options.timeoutMs < 0) {
|
|
106
|
+
throw new TypeError("timeoutMs must be non-negative");
|
|
107
|
+
}
|
|
102
108
|
const id = lockId(key);
|
|
103
109
|
const backends = options.backends ?? DEFAULT_BACKENDS;
|
|
104
110
|
const dir = options.dir ?? join(tmpdir(), "dbx-tools-locks");
|
|
@@ -121,7 +127,7 @@ export async function withFileLock<T>(
|
|
|
121
127
|
const lockPath = join(dir, `${id}.lock`);
|
|
122
128
|
logger.debug("acquiring lock", { backend, key: id, path: lockPath });
|
|
123
129
|
options.onAcquire?.({ backend });
|
|
124
|
-
return holdLockDirectory(lockPath, deadline,
|
|
130
|
+
return holdLockDirectory(lockPath, deadline, fn);
|
|
125
131
|
}
|
|
126
132
|
default: {
|
|
127
133
|
const _exhaustive: never = backend;
|
|
@@ -133,23 +139,6 @@ export async function withFileLock<T>(
|
|
|
133
139
|
throw new Error("withFileLock: no lock backend available");
|
|
134
140
|
}
|
|
135
141
|
|
|
136
|
-
function validateOptions(options: FileLockOptions): void {
|
|
137
|
-
if (options.timeoutMs !== undefined && options.timeoutMs < 0) {
|
|
138
|
-
throw new TypeError("timeoutMs must be non-negative");
|
|
139
|
-
}
|
|
140
|
-
if (options.staleMs !== undefined && options.staleMs <= 0) {
|
|
141
|
-
throw new TypeError("staleMs must be positive");
|
|
142
|
-
}
|
|
143
|
-
if (options.updateMs !== undefined) {
|
|
144
|
-
if (options.staleMs === undefined) {
|
|
145
|
-
throw new TypeError("updateMs requires staleMs");
|
|
146
|
-
}
|
|
147
|
-
if (options.updateMs <= 0 || options.updateMs > options.staleMs / 2) {
|
|
148
|
-
throw new TypeError("updateMs must be positive and no greater than half of staleMs");
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
142
|
/** Canonical filesystem-safe id for a lock key. */
|
|
154
143
|
function lockId(key: unknown): string {
|
|
155
144
|
const stable = object
|
|
@@ -206,7 +195,7 @@ async function holdFlock<T>(
|
|
|
206
195
|
flock(handle.fd, LOCK_UN);
|
|
207
196
|
}
|
|
208
197
|
} finally {
|
|
209
|
-
await handle.close().catch(() => {});
|
|
198
|
+
await handle.close().catch(() => { });
|
|
210
199
|
}
|
|
211
200
|
}
|
|
212
201
|
|
|
@@ -216,7 +205,7 @@ async function waitForFlock(
|
|
|
216
205
|
lockPath: string,
|
|
217
206
|
deadline: number | undefined,
|
|
218
207
|
): Promise<void> {
|
|
219
|
-
for (
|
|
208
|
+
for (; ;) {
|
|
220
209
|
const rc = flock(fd, LOCK_EX | LOCK_NB);
|
|
221
210
|
if (rc === 0) return;
|
|
222
211
|
assertBeforeDeadline(lockPath, deadline);
|
|
@@ -228,51 +217,49 @@ async function waitForFlock(
|
|
|
228
217
|
* Atomic lock-directory creation — the portable / Windows path.
|
|
229
218
|
*
|
|
230
219
|
* `mkdir` is the same primitive used by `proper-lockfile`: it is atomic across
|
|
231
|
-
* supported local and network filesystems.
|
|
232
|
-
*
|
|
220
|
+
* supported local and network filesystems. The holder refreshes mtime on a fixed
|
|
221
|
+
* heartbeat so a live long-running lock is never reclaimed; a crashed holder's
|
|
222
|
+
* directory becomes reclaimable after {@link STALE_MS}.
|
|
233
223
|
*/
|
|
234
224
|
async function holdLockDirectory<T>(
|
|
235
225
|
lockPath: string,
|
|
236
226
|
deadline: number | undefined,
|
|
237
|
-
staleMs: number | undefined,
|
|
238
|
-
updateMs: number | undefined,
|
|
239
227
|
fn: () => T | Promise<T>,
|
|
240
228
|
): Promise<T> {
|
|
241
229
|
await ensureParentDir(lockPath);
|
|
242
|
-
await acquireLockDirectory(lockPath, deadline
|
|
243
|
-
const stopHeartbeat = startHeartbeat(lockPath
|
|
230
|
+
await acquireLockDirectory(lockPath, deadline);
|
|
231
|
+
const stopHeartbeat = startHeartbeat(lockPath);
|
|
244
232
|
try {
|
|
245
233
|
return await fn();
|
|
246
234
|
} finally {
|
|
247
235
|
stopHeartbeat();
|
|
248
|
-
await rm(lockPath, { recursive: true, force: true }).catch(() => {});
|
|
236
|
+
await rm(lockPath, { recursive: true, force: true }).catch(() => { });
|
|
249
237
|
}
|
|
250
238
|
}
|
|
251
239
|
|
|
252
240
|
async function acquireLockDirectory(
|
|
253
241
|
lockPath: string,
|
|
254
242
|
deadline: number | undefined,
|
|
255
|
-
staleMs: number | undefined,
|
|
256
243
|
): Promise<void> {
|
|
257
|
-
for (
|
|
244
|
+
for (; ;) {
|
|
258
245
|
try {
|
|
259
246
|
await mkdir(lockPath);
|
|
260
247
|
return;
|
|
261
248
|
} catch (cause) {
|
|
262
249
|
const err = cause as NodeJS.ErrnoException;
|
|
263
250
|
if (err.code !== "EEXIST") throw error.toError(cause);
|
|
264
|
-
|
|
251
|
+
await maybeReclaimStale(lockPath);
|
|
265
252
|
assertBeforeDeadline(lockPath, deadline);
|
|
266
253
|
await async.sleep(POLL_MS);
|
|
267
254
|
}
|
|
268
255
|
}
|
|
269
256
|
}
|
|
270
257
|
|
|
271
|
-
async function maybeReclaimStale(lockPath: string
|
|
258
|
+
async function maybeReclaimStale(lockPath: string): Promise<void> {
|
|
272
259
|
try {
|
|
273
260
|
const { mtimeMs } = await stat(lockPath);
|
|
274
261
|
const age = Date.now() - mtimeMs;
|
|
275
|
-
if (age <
|
|
262
|
+
if (age < STALE_MS) return;
|
|
276
263
|
logger.debug("reclaiming stale lock directory", { path: lockPath, ageMs: age });
|
|
277
264
|
await rm(lockPath, { recursive: true, force: true });
|
|
278
265
|
} catch (cause) {
|
|
@@ -281,13 +268,7 @@ async function maybeReclaimStale(lockPath: string, staleMs: number): Promise<voi
|
|
|
281
268
|
}
|
|
282
269
|
}
|
|
283
270
|
|
|
284
|
-
function startHeartbeat(
|
|
285
|
-
lockPath: string,
|
|
286
|
-
staleMs: number | undefined,
|
|
287
|
-
updateMs: number | undefined,
|
|
288
|
-
): () => void {
|
|
289
|
-
if (staleMs === undefined) return () => {};
|
|
290
|
-
const intervalMs = updateMs ?? Math.max(1, Math.floor(staleMs / 2));
|
|
271
|
+
function startHeartbeat(lockPath: string): () => void {
|
|
291
272
|
const timer = setInterval(() => {
|
|
292
273
|
const now = new Date();
|
|
293
274
|
void utimes(lockPath, now, now).catch((cause) => {
|
|
@@ -296,7 +277,7 @@ function startHeartbeat(
|
|
|
296
277
|
error: error.errorMessage(cause),
|
|
297
278
|
});
|
|
298
279
|
});
|
|
299
|
-
},
|
|
280
|
+
}, UPDATE_MS);
|
|
300
281
|
timer.unref();
|
|
301
282
|
return () => clearInterval(timer);
|
|
302
283
|
}
|