sliftutils 1.7.88 → 1.7.90
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/.claude/settings.local.json +3 -1
- package/dist/treeSummary.ts.cache +2 -2
- package/index.d.ts +679 -300
- package/misc/dist/environment.ts.cache +2 -2
- package/misc/dist/getSecret.ts.cache +2 -2
- package/misc/dist/strings.ts.cache +2 -2
- package/misc/dist/zip.ts.cache +2 -2
- package/misc/https/dist/certs.ts.cache +2 -2
- package/misc/https/dist/cloudflareHelpers.ts.cache +2 -2
- package/misc/https/dist/dns.ts.cache +2 -2
- package/misc/https/dist/hostServer.ts.cache +49 -21
- package/misc/https/dist/hostsFile.ts.cache +82 -0
- package/misc/https/dist/httpsCerts.ts.cache +2 -2
- package/misc/https/dist/persistentLocalStorage.ts.cache +2 -2
- package/misc/https/hostServer.d.ts +6 -2
- package/misc/https/hostServer.ts +52 -19
- package/misc/https/hostsFile.d.ts +7 -0
- package/misc/https/hostsFile.ts +66 -0
- package/package.json +1 -1
- package/render-utils/dist/observer.tsx.cache +2 -2
- package/storage/ArchivesDisk.d.ts +3 -6
- package/storage/ArchivesDisk.ts +26 -2
- package/storage/BulkDatabase2/BulkDatabaseReader.ts +1 -1
- package/storage/BulkDatabase2/dist/BulkDatabaseBase.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/BulkDatabaseFormat.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/BulkDatabaseMerge.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/BulkDatabaseReader.ts.cache +3 -3
- package/storage/BulkDatabase2/dist/LoadedIndex.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/WriteOverlay.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/blockCache.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/mergeLock.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/mergeMarkers.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/streamLog.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/syncClient.ts.cache +2 -2
- package/storage/IArchives.d.ts +37 -24
- package/storage/IArchives.ts +47 -62
- package/storage/LogMap.d.ts +56 -0
- package/storage/LogMap.ts +220 -0
- package/storage/archiveHelpers.d.ts +36 -0
- package/storage/archiveHelpers.ts +103 -0
- package/storage/backblaze.d.ts +7 -12
- package/storage/backblaze.ts +53 -48
- package/storage/dist/ArchivesDisk.ts.cache +29 -3
- package/storage/dist/FileFolderAPI.tsx.cache +2 -2
- package/storage/dist/IArchives.ts.cache +17 -53
- package/storage/dist/IndexedDBFileFolderAPI.ts.cache +2 -2
- package/storage/dist/JSONStorage.ts.cache +2 -2
- package/storage/dist/LogMap.ts.cache +212 -0
- package/storage/dist/PendingManager.tsx.cache +2 -2
- package/storage/dist/TransactionStorage.ts.cache +2 -2
- package/storage/dist/archiveHelpers.ts.cache +87 -0
- package/storage/dist/backblaze.ts.cache +59 -45
- package/storage/dist/fileSystemPointer.ts.cache +2 -2
- package/storage/dist/remoteFileStorage.ts.cache +2 -2
- package/storage/remoteStorage/ArchivesDelayed.d.ts +66 -0
- package/storage/remoteStorage/ArchivesDelayed.ts +237 -0
- package/storage/remoteStorage/ArchivesRemote.d.ts +5 -6
- package/storage/remoteStorage/ArchivesRemote.ts +26 -5
- package/storage/remoteStorage/ArchivesUrl.d.ts +2 -5
- package/storage/remoteStorage/ArchivesUrl.ts +2 -2
- package/storage/remoteStorage/accessPage.tsx +12 -0
- package/storage/remoteStorage/blobStore.d.ts +162 -189
- package/storage/remoteStorage/blobStore.ts +495 -952
- package/storage/remoteStorage/bucketDisk.d.ts +24 -3
- package/storage/remoteStorage/bucketDisk.ts +56 -22
- package/storage/remoteStorage/certTrustModal.d.ts +1 -0
- package/storage/remoteStorage/certTrustModal.tsx +48 -0
- package/storage/remoteStorage/cliArgs.d.ts +2 -0
- package/storage/remoteStorage/cliArgs.ts +5 -0
- package/storage/remoteStorage/createArchives.d.ts +8 -7
- package/storage/remoteStorage/createArchives.ts +65 -26
- package/storage/remoteStorage/deployTakeover.ts +1 -1
- package/storage/remoteStorage/dist/ArchivesDelayed.ts.cache +220 -0
- package/storage/remoteStorage/dist/ArchivesRemote.ts.cache +26 -6
- package/storage/remoteStorage/dist/ArchivesUrl.ts.cache +3 -3
- package/storage/remoteStorage/dist/accessPage.tsx.cache +13 -3
- package/storage/remoteStorage/dist/accessStats.ts.cache +2 -2
- package/storage/remoteStorage/dist/blobStore.ts.cache +484 -966
- package/storage/remoteStorage/dist/bucketDisk.ts.cache +60 -29
- package/storage/remoteStorage/dist/certTrustModal.tsx.cache +55 -0
- package/storage/remoteStorage/dist/cliArgs.ts.cache +9 -4
- package/storage/remoteStorage/dist/createArchives.ts.cache +64 -27
- package/storage/remoteStorage/dist/deployTakeover.ts.cache +5 -5
- package/storage/remoteStorage/dist/intermediateManagement.ts.cache +286 -0
- package/storage/remoteStorage/dist/intermediateSources.ts.cache +2 -2
- package/storage/remoteStorage/dist/remoteConfig.ts.cache +122 -56
- package/storage/remoteStorage/dist/serverConfig.ts.cache +4 -4
- package/storage/remoteStorage/dist/sourceWrapper.ts.cache +7 -11
- package/storage/remoteStorage/dist/sourcesList.ts.cache +3 -6
- package/storage/remoteStorage/dist/storageClientController.ts.cache +2 -2
- package/storage/remoteStorage/dist/storageController.ts.cache +33 -36
- package/storage/remoteStorage/dist/storageServer.ts.cache +27 -7
- package/storage/remoteStorage/dist/storageServerCli.ts.cache +7 -3
- package/storage/remoteStorage/dist/storageServerState.ts.cache +138 -707
- package/storage/remoteStorage/dist/storeConfig.ts.cache +52 -0
- package/storage/remoteStorage/dist/storePlan.ts.cache +110 -81
- package/storage/remoteStorage/dist/storeSources.ts.cache +51 -0
- package/storage/remoteStorage/dist/storeSync.ts.cache +651 -0
- package/storage/remoteStorage/dist/validation.ts.cache +14 -4
- package/storage/remoteStorage/intermediateManagement.d.ts +12 -0
- package/storage/remoteStorage/intermediateManagement.ts +264 -0
- package/storage/remoteStorage/remoteConfig.d.ts +32 -0
- package/storage/remoteStorage/remoteConfig.ts +115 -50
- package/storage/remoteStorage/serverConfig.d.ts +1 -1
- package/storage/remoteStorage/serverConfig.ts +1 -1
- package/storage/remoteStorage/sourceWrapper.ts +4 -8
- package/storage/remoteStorage/sourcesList.d.ts +0 -2
- package/storage/remoteStorage/sourcesList.ts +0 -3
- package/storage/remoteStorage/spec.md +18 -4
- package/storage/remoteStorage/storageController.d.ts +10 -0
- package/storage/remoteStorage/storageController.ts +37 -41
- package/storage/remoteStorage/storageServer.d.ts +2 -0
- package/storage/remoteStorage/storageServer.ts +28 -4
- package/storage/remoteStorage/storageServerCli.ts +5 -1
- package/storage/remoteStorage/storageServerState.d.ts +39 -26
- package/storage/remoteStorage/storageServerState.ts +149 -669
- package/storage/remoteStorage/storeConfig.d.ts +30 -0
- package/storage/remoteStorage/storeConfig.ts +62 -0
- package/storage/remoteStorage/storePlan.d.ts +29 -17
- package/storage/remoteStorage/storePlan.ts +112 -85
- package/storage/remoteStorage/storeSources.d.ts +11 -0
- package/storage/remoteStorage/storeSources.ts +47 -0
- package/storage/remoteStorage/storeSync.d.ts +53 -0
- package/storage/remoteStorage/storeSync.ts +632 -0
- package/storage/remoteStorage/validation.d.ts +2 -0
- package/storage/remoteStorage/validation.ts +10 -0
|
@@ -1,36 +1,15 @@
|
|
|
1
1
|
"use strict"; var console = (function shimConsole() { let baseConsole = globalThis.console; if (typeof window !== "undefined") return baseConsole; let name = __filename.replaceAll("\\", "/").split("/").pop(); let dirName = __dirname.replaceAll("\\", "/").split("/").pop(); let context = { __FILE__: __filename, __DIR__: __dirname, __NAME__: name, __DIRNAME__: dirName }; let newConsole = { ...baseConsole }; for (let shim of ["log", "info", "warn", "error"]) { newConsole[shim] = (...args) => { args.push(context); baseConsole[shim](...args); }; } newConsole.__context = context; return newConsole; })(); "use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule && mod.default) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
|
|
6
|
-
//exports.
|
|
7
|
-
const path_1 = __importDefault(require("path"));
|
|
8
|
-
const fs_1 = __importDefault(require("fs"));
|
|
9
|
-
const caching_1 = require("socket-function/src/caching");
|
|
10
|
-
const misc_1 = require("socket-function/src/misc");
|
|
11
|
-
const batching_1 = require("socket-function/src/batching");
|
|
12
|
-
const ArchivesDisk_1 = require("../ArchivesDisk");
|
|
3
|
+
//exports.debugClearAccountWriteStats = exports.debugListAccountBuckets = exports.activateBucket = exports.debugGetActiveBucket = exports.getActiveBucketKeys = exports.writeRoutingConfig = exports.reloadBucket = exports.getLoadedBucket = exports.getStore = exports.resolveSourceArchives = exports.getBucketStates = exports.debugBucketIndexTotals = exports.bucketSyncStatus = exports.getBucketConfig = exports.readBucketInternal = exports.findBucketStore = exports.requireBucket = void 0;
|
|
13
4
|
const blobStore_1 = require("./blobStore");
|
|
14
|
-
const IArchives_1 = require("../IArchives");
|
|
15
5
|
const remoteConfig_1 = require("./remoteConfig");
|
|
16
|
-
const
|
|
17
|
-
const deployTakeover_1 = require("./deployTakeover");
|
|
18
|
-
const createArchives_1 = require("./createArchives");
|
|
6
|
+
const storeSources_1 = require("./storeSources");
|
|
19
7
|
const storageController_1 = require("./storageController");
|
|
20
8
|
const serverConfig_1 = require("./serverConfig");
|
|
9
|
+
const validation_1 = require("./validation");
|
|
21
10
|
const bucketDisk_1 = require("./bucketDisk");
|
|
11
|
+
const intermediateManagement_1 = require("./intermediateManagement");
|
|
22
12
|
const storePlan_1 = require("./storePlan");
|
|
23
|
-
/** JSON with sorted object keys and undefined-valued keys dropped, so two configs that mean the same thing compare equal regardless of key order or which side serialized them. */
|
|
24
|
-
function stableStringify(value) {
|
|
25
|
-
if (!value || typeof value !== "object")
|
|
26
|
-
return JSON.stringify(value);
|
|
27
|
-
if (Array.isArray(value)) {
|
|
28
|
-
return `[${value.map(x => stableStringify(x)).join(",")}]`;
|
|
29
|
-
}
|
|
30
|
-
let entries = Object.entries(value).filter(x => x[1] !== undefined);
|
|
31
|
-
(0, misc_1.sort)(entries, x => x[0]);
|
|
32
|
-
return `{${entries.map(([key, child]) => `${JSON.stringify(key)}:${stableStringify(child)}`).join(",")}}`;
|
|
33
|
-
}
|
|
34
13
|
/** The loaded bucket, loading it (which instantiates its stores and starts their synchronization) if needed. A bucket that does not exist on this server throws - callers never see undefined buckets. */
|
|
35
14
|
async function requireBucket(account, bucketName) {
|
|
36
15
|
let bucket = await getLoadedBucket(account, bucketName);
|
|
@@ -40,23 +19,14 @@ async function requireBucket(account, bucketName) {
|
|
|
40
19
|
return bucket;
|
|
41
20
|
}
|
|
42
21
|
exports.requireBucket = requireBucket;
|
|
43
|
-
/** The
|
|
44
|
-
function
|
|
45
|
-
let url = config.intermediate || config.url;
|
|
46
|
-
return stableStringify({ ...config, url, intermediate: undefined, validWindow: undefined });
|
|
47
|
-
}
|
|
48
|
-
/** The store serving a request: the config entry the CLIENT selected, matched against the bucket's own entries by identity EXCLUDING the valid window (see sourceMatchKey). The selection never validates - the store's own window/route checks throw if the caller is stale - so honoring a window mismatch here is exactly right. Throws when nothing matches, listing what is available. */
|
|
49
|
-
async function findBucketStore(account, bucketName, sourceConfig) {
|
|
50
|
-
let bucket = await requireBucket(account, bucketName);
|
|
22
|
+
/** The store serving a request: the one the client's selected entry NAMES. Account, name, and bucket ARE the folder, so this is a direct lookup, never a search of what exists - and a name this server has never seen is CREATED, never rejected, because asking for a name is the instruction to have that store (one name, one folder, one index; it configures itself once the routing config lands in it). Nothing else about the request is compared - not the window, not the route, not the flags - which is the whole point of naming it: a client a config version behind on some flag still reaches the right store. */
|
|
23
|
+
function findBucketStore(account, bucketName, sourceConfig) {
|
|
51
24
|
if (!sourceConfig) {
|
|
52
|
-
throw new Error(`No remote source configuration was provided for bucket ${account}/${bucketName}: every request must say which configured source it selected
|
|
53
|
-
}
|
|
54
|
-
let wanted = sourceMatchKey(sourceConfig);
|
|
55
|
-
for (let s of bucket.stores) {
|
|
56
|
-
if (s.entries.some(e => sourceMatchKey(e) === wanted))
|
|
57
|
-
return s;
|
|
25
|
+
throw new Error(`No remote source configuration was provided for bucket ${account}/${bucketName}: every request must say which configured source it selected`);
|
|
58
26
|
}
|
|
59
|
-
|
|
27
|
+
// Not part of resolving the request (the name already says everything): loading the bucket is what schedules its switchover work and marks it active for deploy handoffs, and a bucket serving requests must be loaded
|
|
28
|
+
void getLoadedBucket(account, bucketName).catch((e) => { var _a; return console.error(`Loading bucket ${account}/${bucketName} failed: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`); });
|
|
29
|
+
return getStore(account, bucketName, sourceConfig.name);
|
|
60
30
|
}
|
|
61
31
|
exports.findBucketStore = findBucketStore;
|
|
62
32
|
/** Internal (store-to-store) reads skip store selection entirely: the caller is another store whose index says this MACHINE holds the bytes - the persisted holder identity is just a URL, which cannot name a store. Whichever store's folder has the newest copy answers. */
|
|
@@ -73,15 +43,12 @@ async function readBucketInternal(account, bucketName, config) {
|
|
|
73
43
|
}
|
|
74
44
|
exports.readBucketInternal = readBucketInternal;
|
|
75
45
|
function getBucketConfig(bucket) {
|
|
76
|
-
var _a, _b;
|
|
77
46
|
let index = { fileCount: 0, byteCount: 0 };
|
|
78
47
|
let indexSources = [];
|
|
79
48
|
let syncing = [];
|
|
80
49
|
let readerDiskLimit;
|
|
81
50
|
for (let s of bucket.stores) {
|
|
82
|
-
let progress =
|
|
83
|
-
if (!progress)
|
|
84
|
-
continue;
|
|
51
|
+
let progress = s.store.getSyncProgress();
|
|
85
52
|
index.fileCount += progress.index.fileCount;
|
|
86
53
|
index.byteCount += progress.index.byteCount;
|
|
87
54
|
indexSources.push(...progress.sources);
|
|
@@ -89,8 +56,8 @@ function getBucketConfig(bucket) {
|
|
|
89
56
|
readerDiskLimit = readerDiskLimit || progress.readerDiskLimit;
|
|
90
57
|
}
|
|
91
58
|
return {
|
|
92
|
-
//
|
|
93
|
-
supportsChangesAfter:
|
|
59
|
+
// Every store is index-backed, so the change feed is always native
|
|
60
|
+
supportsChangesAfter: true,
|
|
94
61
|
remoteConfig: bucket.routing,
|
|
95
62
|
index,
|
|
96
63
|
indexSources,
|
|
@@ -100,17 +67,7 @@ function getBucketConfig(bucket) {
|
|
|
100
67
|
}
|
|
101
68
|
exports.getBucketConfig = getBucketConfig;
|
|
102
69
|
async function bucketSyncStatus(bucket) {
|
|
103
|
-
let
|
|
104
|
-
if (!supported.length) {
|
|
105
|
-
throw new Error(`Bucket ${bucket.account}/${bucket.bucketName} does not support getSyncStatus (rawDisk buckets have no synchronization)`);
|
|
106
|
-
}
|
|
107
|
-
let statuses = await Promise.all(supported.map(async (s) => {
|
|
108
|
-
let getSyncStatus = s.store.getSyncStatus;
|
|
109
|
-
if (!getSyncStatus) {
|
|
110
|
-
throw new Error(`getSyncStatus disappeared from a store for ${bucket.account}/${bucket.bucketName}`);
|
|
111
|
-
}
|
|
112
|
-
return await getSyncStatus.call(s.store);
|
|
113
|
-
}));
|
|
70
|
+
let statuses = await Promise.all(bucket.stores.map(s => s.store.getSyncStatus()));
|
|
114
71
|
return {
|
|
115
72
|
allScansComplete: statuses.every(x => x.allScansComplete),
|
|
116
73
|
indexSize: statuses.reduce((sum, x) => sum + x.indexSize, 0),
|
|
@@ -118,426 +75,145 @@ async function bucketSyncStatus(bucket) {
|
|
|
118
75
|
};
|
|
119
76
|
}
|
|
120
77
|
exports.bucketSyncStatus = bucketSyncStatus;
|
|
121
|
-
async function
|
|
122
|
-
let
|
|
123
|
-
if (!supported.length)
|
|
124
|
-
return undefined;
|
|
125
|
-
let totals = await Promise.all(supported.map(async (s) => {
|
|
126
|
-
let computeIndexTotals = s.store.computeIndexTotals;
|
|
127
|
-
if (!computeIndexTotals) {
|
|
128
|
-
throw new Error(`computeIndexTotals disappeared from a store for ${bucket.account}/${bucket.bucketName}`);
|
|
129
|
-
}
|
|
130
|
-
return await computeIndexTotals.call(s.store);
|
|
131
|
-
}));
|
|
78
|
+
async function debugBucketIndexTotals(bucket) {
|
|
79
|
+
let totals = await Promise.all(bucket.stores.map(s => s.store.computeIndexTotals()));
|
|
132
80
|
return {
|
|
133
81
|
fileCount: totals.reduce((sum, x) => sum + x.fileCount, 0),
|
|
134
82
|
byteCount: totals.reduce((sum, x) => sum + x.byteCount, 0),
|
|
135
83
|
sources: totals.flatMap(x => x.sources),
|
|
136
84
|
};
|
|
137
85
|
}
|
|
138
|
-
exports.
|
|
86
|
+
exports.debugBucketIndexTotals = debugBucketIndexTotals;
|
|
139
87
|
const buckets = new Map();
|
|
140
|
-
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
let boundaries = loaded.selfEntries.flatMap(x => x.validWindow).filter(t => t > now);
|
|
146
|
-
if (!boundaries.length)
|
|
147
|
-
return;
|
|
148
|
-
let nextBoundary = Math.min(...boundaries);
|
|
149
|
-
let key = `${loaded.account}/${loaded.bucketName}`;
|
|
150
|
-
let timer = setTimeout(() => {
|
|
151
|
-
void (async () => {
|
|
152
|
-
let current = await buckets.get(key);
|
|
153
|
-
if (current !== loaded)
|
|
154
|
-
return;
|
|
155
|
-
if (Date.now() < nextBoundary) {
|
|
156
|
-
scheduleWindowBoundaryRebuild(loaded);
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
await scheduleRoutingReload(loaded.account, loaded.bucketName, { force: true, reason: "a valid window boundary passed" });
|
|
160
|
-
})();
|
|
161
|
-
}, Math.min(nextBoundary - now + REBUILD_BOUNDARY_BUFFER, MAX_REBUILD_TIMER_DELAY));
|
|
162
|
-
(_b = (_a = timer).unref) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
163
|
-
}
|
|
164
|
-
const BOUNDARY_SCAN_OFFSETS = [-30 * 1000, 2 * 1000, 30 * 1000];
|
|
165
|
-
const BOUNDARY_SCAN_LOOKBACK = blobStore_1.DEFAULT_FAST_WRITE_DELAY + blobStore_1.WINDOW_END_FLUSH_MARGIN;
|
|
166
|
-
const STARTUP_BOUNDARY_SCAN_DELAY = 30 * 1000;
|
|
167
|
-
const scheduledBoundaryScans = new Set();
|
|
168
|
-
const boundaryScansRunning = new Set();
|
|
169
|
-
function scheduleBoundaryScans(loaded) {
|
|
170
|
-
var _a, _b;
|
|
171
|
-
let key = `${loaded.account}/${loaded.bucketName}`;
|
|
172
|
-
let now = Date.now();
|
|
173
|
-
let starts = new Set();
|
|
174
|
-
for (let self of loaded.selfEntries) {
|
|
175
|
-
let start = self.validWindow[0];
|
|
176
|
-
if (start > now && start < Number.MAX_SAFE_INTEGER) {
|
|
177
|
-
starts.add(start);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
for (let self of loaded.selfEntries) {
|
|
181
|
-
let [start, end] = self.validWindow;
|
|
182
|
-
if (!(start <= now && now < end) || start <= 0)
|
|
183
|
-
continue;
|
|
184
|
-
if (now - start > BOUNDARY_SCAN_LOOKBACK)
|
|
185
|
-
continue;
|
|
186
|
-
let scheduleKey = `${key}|${start}|startup`;
|
|
187
|
-
if (scheduledBoundaryScans.has(scheduleKey))
|
|
188
|
-
continue;
|
|
189
|
-
scheduledBoundaryScans.add(scheduleKey);
|
|
190
|
-
let timer = setTimeout(() => {
|
|
191
|
-
void runBoundaryScan(key, start, STARTUP_BOUNDARY_SCAN_DELAY, "startup+30s").catch((e) => { var _a; return console.error(`Boundary scan for bucket ${key} failed: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`); });
|
|
192
|
-
}, STARTUP_BOUNDARY_SCAN_DELAY);
|
|
193
|
-
(_b = (_a = timer).unref) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
194
|
-
}
|
|
195
|
-
for (let start of starts) {
|
|
196
|
-
for (let offset of BOUNDARY_SCAN_OFFSETS) {
|
|
197
|
-
let at = start + offset;
|
|
198
|
-
if (at <= now)
|
|
199
|
-
continue;
|
|
200
|
-
let scheduleKey = `${key}|${start}|${offset}`;
|
|
201
|
-
if (scheduledBoundaryScans.has(scheduleKey))
|
|
202
|
-
continue;
|
|
203
|
-
scheduledBoundaryScans.add(scheduleKey);
|
|
204
|
-
let arm = () => {
|
|
205
|
-
var _a, _b;
|
|
206
|
-
let timer = setTimeout(() => {
|
|
207
|
-
if (Date.now() < at) {
|
|
208
|
-
arm();
|
|
209
|
-
return;
|
|
210
|
-
}
|
|
211
|
-
void runBoundaryScan(key, start, offset).catch((e) => { var _a; return console.error(`Boundary scan for bucket ${key} failed: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`); });
|
|
212
|
-
}, Math.min(at - Date.now(), MAX_REBUILD_TIMER_DELAY));
|
|
213
|
-
(_b = (_a = timer).unref) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
214
|
-
};
|
|
215
|
-
arm();
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
async function runBoundaryScan(bucketKey, windowStart, offset, offsetLabel) {
|
|
220
|
-
var _a;
|
|
221
|
-
let label = `bucket ${bucketKey}, window starting ${new Date(windowStart).toISOString()}, offset ${offsetLabel || `${offset / 1000}s`}`;
|
|
222
|
-
if (boundaryScansRunning.has(bucketKey)) {
|
|
223
|
-
console.log(`Skipping boundary scan (${label}): the previous boundary scan is still running`);
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
boundaryScansRunning.add(bucketKey);
|
|
227
|
-
try {
|
|
228
|
-
let loaded = await buckets.get(bucketKey);
|
|
229
|
-
if (!loaded)
|
|
230
|
-
return;
|
|
231
|
-
let effective = loaded.routing;
|
|
232
|
-
let selfIndexes = (0, storePlan_1.findSelfIndexes)(effective, loaded.account, loaded.bucketName);
|
|
233
|
-
let selfIndexSet = new Set(selfIndexes);
|
|
234
|
-
let selves = selfIndexes.map(i => effective.sources[i]).filter(x => x.validWindow[0] === windowStart);
|
|
235
|
-
if (!selves.length)
|
|
236
|
-
return;
|
|
237
|
-
let prevTime = windowStart - 1;
|
|
238
|
-
// Everything is per-store: each self entry's route has its own store, and that store's disk/remote boundary pulls only concern its own route slice
|
|
239
|
-
let needDiskScan = new Set();
|
|
240
|
-
let remoteOwners = new Map();
|
|
241
|
-
for (let self of selves) {
|
|
242
|
-
let selfRoute = self.route || IArchives_1.FULL_ROUTE;
|
|
243
|
-
let selfStore = loaded.stores.find(x => x.routeKey === JSON.stringify(selfRoute));
|
|
244
|
-
if (!selfStore || !(selfStore.store instanceof blobStore_1.BlobStore))
|
|
245
|
-
continue;
|
|
246
|
-
let idx = effective.sources.indexOf(self);
|
|
247
|
-
let shadowed = false;
|
|
248
|
-
for (let j = 0; j < idx; j++) {
|
|
249
|
-
let other = effective.sources[j];
|
|
250
|
-
if (typeof other === "string")
|
|
251
|
-
continue;
|
|
252
|
-
let [ws, we] = other.validWindow;
|
|
253
|
-
if (!(ws <= windowStart && windowStart < we))
|
|
254
|
-
continue;
|
|
255
|
-
let r = other.route || IArchives_1.FULL_ROUTE;
|
|
256
|
-
if (r[0] <= selfRoute[0] && selfRoute[1] <= r[1]) {
|
|
257
|
-
shadowed = true;
|
|
258
|
-
break;
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
if (shadowed)
|
|
262
|
-
continue;
|
|
263
|
-
let uncovered = [[selfRoute[0], selfRoute[1]]];
|
|
264
|
-
for (let j = 0; j < effective.sources.length && uncovered.length; j++) {
|
|
265
|
-
let other = effective.sources[j];
|
|
266
|
-
if (typeof other === "string")
|
|
267
|
-
continue;
|
|
268
|
-
let [ws, we] = other.validWindow;
|
|
269
|
-
if (!(ws <= prevTime && prevTime < we))
|
|
270
|
-
continue;
|
|
271
|
-
let r = other.route || IArchives_1.FULL_ROUTE;
|
|
272
|
-
let remaining = [];
|
|
273
|
-
let claimed;
|
|
274
|
-
for (let u of uncovered) {
|
|
275
|
-
let inter = (0, remoteConfig_1.routeIntersection)(u, r);
|
|
276
|
-
if (!inter) {
|
|
277
|
-
remaining.push(u);
|
|
278
|
-
continue;
|
|
279
|
-
}
|
|
280
|
-
claimed = claimed && [Math.min(claimed[0], inter[0]), Math.max(claimed[1], inter[1])] || inter;
|
|
281
|
-
if (u[0] < inter[0])
|
|
282
|
-
remaining.push([u[0], inter[0]]);
|
|
283
|
-
if (inter[1] < u[1])
|
|
284
|
-
remaining.push([inter[1], u[1]]);
|
|
285
|
-
}
|
|
286
|
-
uncovered = remaining;
|
|
287
|
-
if (!claimed)
|
|
288
|
-
continue;
|
|
289
|
-
if (selfIndexSet.has(j)) {
|
|
290
|
-
needDiskScan.add(selfStore);
|
|
291
|
-
}
|
|
292
|
-
else {
|
|
293
|
-
let owners = remoteOwners.get(selfStore);
|
|
294
|
-
if (!owners) {
|
|
295
|
-
owners = new Map();
|
|
296
|
-
remoteOwners.set(selfStore, owners);
|
|
297
|
-
}
|
|
298
|
-
let existing = owners.get(j);
|
|
299
|
-
owners.set(j, existing && [Math.min(existing[0], claimed[0]), Math.max(existing[1], claimed[1])] || claimed);
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
if (!needDiskScan.size && !remoteOwners.size)
|
|
304
|
-
return;
|
|
305
|
-
console.log(`Boundary scan (${label}): diskScans=${needDiskScan.size}, stores with remote previous-window owners: ${remoteOwners.size}`);
|
|
306
|
-
for (let selfStore of needDiskScan) {
|
|
307
|
-
if (selfStore.store instanceof blobStore_1.BlobStore) {
|
|
308
|
-
await selfStore.store.rescanBase();
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
let since = windowStart - BOUNDARY_SCAN_LOOKBACK;
|
|
312
|
-
for (let [selfStore, owners] of remoteOwners) {
|
|
313
|
-
if (!(selfStore.store instanceof blobStore_1.BlobStore))
|
|
314
|
-
continue;
|
|
315
|
-
for (let [sourceIndex, route] of owners) {
|
|
316
|
-
let ownerSource = effective.sources[sourceIndex];
|
|
317
|
-
if (typeof ownerSource === "string")
|
|
318
|
-
continue;
|
|
319
|
-
try {
|
|
320
|
-
await selfStore.store.boundaryScanRemote((0, createArchives_1.createApiArchives)(ownerSource), { since, route });
|
|
321
|
-
}
|
|
322
|
-
catch (e) {
|
|
323
|
-
console.error(`Boundary scan (${label}) of previous-window owner (source index ${sourceIndex}) failed: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
finally {
|
|
329
|
-
boundaryScansRunning.delete(bucketKey);
|
|
330
|
-
}
|
|
88
|
+
// The resolved ones, for the code that walks buckets rather than asking for one (see getBucketStates)
|
|
89
|
+
const loadedBuckets = new Map();
|
|
90
|
+
/** The bucket states currently in memory - what the switchover machinery walks. Only what is loaded: loading a bucket starts its synchronization, and a bucket nothing has touched has no in-flight writes to hand over anyway. */
|
|
91
|
+
function getBucketStates() {
|
|
92
|
+
return [...loadedBuckets.values()];
|
|
331
93
|
}
|
|
94
|
+
exports.getBucketStates = getBucketStates;
|
|
332
95
|
const resolvedSourceArchives = new Map();
|
|
333
96
|
/** A cached IArchives for a persisted source identity: a routing URL (hosted/backblaze) or a disk folder path - the form BlobStore's sources list stores. Configuration (valid windows, routes) decides WHEN a source should be used; for reading bytes the index says a source holds, the URL alone is enough - even for sources no longer in any config. */
|
|
334
97
|
function resolveSourceArchives(url) {
|
|
335
98
|
let existing = resolvedSourceArchives.get(url);
|
|
336
99
|
if (existing)
|
|
337
100
|
return existing;
|
|
338
|
-
let
|
|
101
|
+
let sourceConfig;
|
|
339
102
|
if (url.startsWith("https://")) {
|
|
340
103
|
// The config is fabricated from the bare URL and can never exact-match a server's entries - which is fine, because holder reads are internal reads, and internal reads never select a store (see readBucketInternal)
|
|
341
|
-
|
|
342
|
-
}
|
|
343
|
-
else {
|
|
344
|
-
archives = new ArchivesDisk_1.ArchivesDisk(url);
|
|
104
|
+
sourceConfig = (0, remoteConfig_1.normalizeSource)(url);
|
|
345
105
|
}
|
|
106
|
+
let archives = (0, storeSources_1.createStoreSource)({ sourceConfig, folder: url });
|
|
346
107
|
resolvedSourceArchives.set(url, archives);
|
|
347
108
|
return archives;
|
|
348
109
|
}
|
|
349
110
|
exports.resolveSourceArchives = resolveSourceArchives;
|
|
350
|
-
|
|
111
|
+
/** What an index entry records as the holder of its bytes (see ArchivesSource.url), so it must name the endpoint FOREVER. An intermediate is a switchover's temporary alternate port onto another source, and that port is gone for good once its window passes - so it is recorded as the source it was split out of, which holds the same bucket and outlives it. */
|
|
112
|
+
function sourcePersistentUrl(sourceConfig, folder) {
|
|
351
113
|
if (!sourceConfig)
|
|
352
|
-
return
|
|
353
|
-
return
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
114
|
+
return folder;
|
|
115
|
+
return sourceConfig.intermediate || sourceConfig.url;
|
|
116
|
+
}
|
|
117
|
+
/** The fast-write policy this store writes under: its own configuration decides it (fast/writeDelay are OUR settings, not the peer's), and each source then holds writes for as long as sourceWriteDelay says. */
|
|
118
|
+
/**
|
|
119
|
+
* Every store this process runs, by folder - which IS the store's identity: account, name, bucket.
|
|
120
|
+
* A store is made once, configures itself from the routing config it holds, and stays; nothing here
|
|
121
|
+
* decides what it is, only that it exists.
|
|
122
|
+
*/
|
|
123
|
+
const stores = new Map();
|
|
124
|
+
function getStore(account, bucketName, name) {
|
|
125
|
+
// The one place a name becomes a folder, so the one place it is validated (it can come straight off the wire)
|
|
126
|
+
(0, validation_1.assertValidSourceName)(name);
|
|
127
|
+
let folder = (0, bucketDisk_1.getBucketFolder)(name, account, bucketName);
|
|
128
|
+
let existing = stores.get(folder);
|
|
129
|
+
if (existing)
|
|
130
|
+
return existing;
|
|
131
|
+
console.log(`Opening store ${JSON.stringify(name)} of bucket ${account}/${bucketName} (folder ${folder}) - created on this first use if it never existed`);
|
|
132
|
+
let store = new blobStore_1.BlobStore(folder, name, {
|
|
133
|
+
// Which entries in ITS routing config are this server's copy of it
|
|
134
|
+
isSelf: source => (0, storePlan_1.isSelfSource)(source, account, bucketName),
|
|
135
|
+
createSource: config => (0, storeSources_1.createStoreSource)({ sourceConfig: config.sourceConfig, folder, writeDelay: config.writeDelay }),
|
|
136
|
+
applySource: (source, sourceConfig, writeDelay) => (0, storeSources_1.applySourceConfig)(source, sourceConfig, writeDelay),
|
|
375
137
|
onWriteCounted: (kind, bytes) => countBucketWrite(`${account}/${bucketName}`, kind, bytes),
|
|
376
138
|
resolveSourceUrl: resolveSourceArchives,
|
|
377
|
-
entries: planStore.entries,
|
|
378
139
|
});
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
let
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
140
|
+
stores.set(folder, store);
|
|
141
|
+
// Lazy init would leave a store nothing has touched sitting inert - no index loaded, no config applied, nothing synchronizing - while its folder is full of files
|
|
142
|
+
void store.init().catch((e) => { var _a; return console.error(`Initializing store ${JSON.stringify(name)} of bucket ${account}/${bucketName} failed: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`); });
|
|
143
|
+
return store;
|
|
144
|
+
}
|
|
145
|
+
exports.getStore = getStore;
|
|
146
|
+
/** The bucket as this server has it: the stores whose folders exist, plus whatever the newest of their configs says about us. Names come from the DISK, not from the config - a store we hold keeps being served whether or not the current config still mentions it. */
|
|
147
|
+
function buildBucket(account, bucketName, names, routing) {
|
|
148
|
+
let plan = routing && (0, storePlan_1.planSelfStores)(account, bucketName, routing) || undefined;
|
|
149
|
+
let entriesByName = new Map();
|
|
150
|
+
for (let selfStore of (plan === null || plan === void 0 ? void 0 : plan.stores) || []) {
|
|
151
|
+
entriesByName.set(selfStore.name, selfStore.entries);
|
|
152
|
+
}
|
|
153
|
+
// Each store reads its own copy of the config and decides what it is - see BlobStore.applyRoutingConfig. Nothing here configures anything.
|
|
154
|
+
let stores = names.map(name => ({
|
|
155
|
+
name,
|
|
156
|
+
entries: entriesByName.get(name) || [],
|
|
157
|
+
folder: (0, bucketDisk_1.getBucketFolder)(name, account, bucketName),
|
|
158
|
+
store: getStore(account, bucketName, name),
|
|
394
159
|
}));
|
|
395
|
-
let loaded = { account, bucketName, routing,
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
// A loaded bucket must actually be running: each store's init loads its index and starts its source synchronization, and it is lazy, so without this a bucket nothing has read from or written to sits inert - reporting no data and no syncing while its disk is full of files.
|
|
399
|
-
for (let s of stores) {
|
|
400
|
-
if (s.store instanceof blobStore_1.BlobStore) {
|
|
401
|
-
let store = s.store;
|
|
402
|
-
void store.init().catch((e) => { var _a; return console.error(`Initializing the store for bucket ${account}/${bucketName} (route ${s.routeKey}) failed: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`); });
|
|
403
|
-
}
|
|
404
|
-
}
|
|
160
|
+
let loaded = { account, bucketName, routing, selfEntries: (plan === null || plan === void 0 ? void 0 : plan.selfEntries) || [], self: plan === null || plan === void 0 ? void 0 : plan.self, stores };
|
|
161
|
+
loadedBuckets.set(`${account}/${bucketName}`, loaded);
|
|
162
|
+
(0, intermediateManagement_1.scheduleBoundaryWork)(loaded);
|
|
405
163
|
return loaded;
|
|
406
164
|
}
|
|
165
|
+
// A bucket exists here when it has at least one store folder - the disk IS the record. Its config is the newest copy among those stores; with none at all it has no config yet, which is a perfectly good state for a store nobody has configured.
|
|
407
166
|
async function loadBucket(account, bucketName) {
|
|
408
|
-
let
|
|
409
|
-
if (!
|
|
167
|
+
let folders = await (0, bucketDisk_1.listBucketStoreFolders)(account, bucketName);
|
|
168
|
+
if (!folders.length)
|
|
410
169
|
return undefined;
|
|
411
|
-
|
|
170
|
+
let routing = await (0, bucketDisk_1.readRoutingFromDisk)(account, bucketName);
|
|
171
|
+
return buildBucket(account, bucketName, folders.map(x => x.name), routing);
|
|
412
172
|
}
|
|
413
173
|
function getLoadedBucket(account, bucketName) {
|
|
414
174
|
let key = `${account}/${bucketName}`;
|
|
415
|
-
|
|
416
|
-
if (!loaded) {
|
|
417
|
-
loaded = loadBucket(account, bucketName);
|
|
418
|
-
buckets.set(key, loaded);
|
|
419
|
-
void loaded.then(bucket => {
|
|
420
|
-
if (!bucket && buckets.get(key) === loaded) {
|
|
421
|
-
buckets.delete(key);
|
|
422
|
-
}
|
|
423
|
-
}, () => {
|
|
424
|
-
if (buckets.get(key) === loaded) {
|
|
425
|
-
buckets.delete(key);
|
|
426
|
-
}
|
|
427
|
-
});
|
|
428
|
-
}
|
|
429
|
-
return loaded;
|
|
175
|
+
return buckets.get(key) || reloadBucket(account, bucketName);
|
|
430
176
|
}
|
|
431
177
|
exports.getLoadedBucket = getLoadedBucket;
|
|
432
|
-
|
|
433
|
-
function
|
|
178
|
+
/** Re-reads the bucket off the disk, replacing the cached snapshot: what a routing-config write calls, because that write can CREATE a store (a new name gets a new folder) and the snapshot would keep answering with the stores it saw at load time. Existing stores are reused (getStore caches by folder), so this only picks up folder changes - it never restarts a store. */
|
|
179
|
+
async function reloadBucket(account, bucketName) {
|
|
434
180
|
let key = `${account}/${bucketName}`;
|
|
435
|
-
let
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
}
|
|
441
|
-
async function checkRoutingChanged(account, bucketName, config) {
|
|
442
|
-
let key = `${account}/${bucketName}`;
|
|
443
|
-
let loaded = await buckets.get(key);
|
|
444
|
-
if (!loaded)
|
|
445
|
-
return;
|
|
446
|
-
let routing = await (0, bucketDisk_1.readRoutingFromDisk)(account, bucketName);
|
|
447
|
-
if (!routing)
|
|
448
|
-
return;
|
|
449
|
-
if (!(config === null || config === void 0 ? void 0 : config.force) && JSON.stringify(routing) === loaded.routingJSON)
|
|
450
|
-
return;
|
|
451
|
-
let reason = (config === null || config === void 0 ? void 0 : config.force) && (config.reason || "forced") || "routing config changed";
|
|
452
|
-
let plan = (0, storePlan_1.computeStorePlan)(account, bucketName, routing);
|
|
453
|
-
if (plan.structureKey === loaded.structureKey) {
|
|
454
|
-
console.log(`Applying the routing config to the running stores for bucket ${key} (${reason})`);
|
|
455
|
-
for (let planStore of plan.stores) {
|
|
456
|
-
let live = loaded.stores.find(x => x.routeKey === planStore.routeKey);
|
|
457
|
-
// structureKey equality means the store set (routes, rawDisk, limits) is unchanged, so every plan store has its live twin
|
|
458
|
-
if (!live || !(live.store instanceof blobStore_1.BlobStore))
|
|
459
|
-
continue;
|
|
460
|
-
let storeFolder = live.folder;
|
|
461
|
-
live.store.updateSources(planStore.sourceSpecs.map(spec => {
|
|
462
|
-
const sourceConfig = spec.sourceConfig;
|
|
463
|
-
if (!sourceConfig) {
|
|
464
|
-
return { identity: sourceIdentity(undefined), url: storeFolder, validWindows: spec.validWindows, create: () => new ArchivesDisk_1.ArchivesDisk(storeFolder) };
|
|
465
|
-
}
|
|
466
|
-
return {
|
|
467
|
-
identity: sourceIdentity(sourceConfig),
|
|
468
|
-
url: sourceConfig.url,
|
|
469
|
-
validWindows: spec.validWindows,
|
|
470
|
-
route: spec.route,
|
|
471
|
-
noFullSync: spec.noFullSync,
|
|
472
|
-
intermediate: sourceConfig.intermediate,
|
|
473
|
-
sourceConfig,
|
|
474
|
-
create: () => (0, createArchives_1.createApiArchives)(sourceConfig),
|
|
475
|
-
};
|
|
476
|
-
}), planStore.entries);
|
|
477
|
-
live.entries = planStore.entries;
|
|
181
|
+
let loaded = loadBucket(account, bucketName);
|
|
182
|
+
buckets.set(key, loaded);
|
|
183
|
+
void loaded.then(bucket => {
|
|
184
|
+
if (!bucket && buckets.get(key) === loaded) {
|
|
185
|
+
buckets.delete(key);
|
|
478
186
|
}
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
loaded.self = plan.self;
|
|
483
|
-
scheduleWindowBoundaryRebuild(loaded);
|
|
484
|
-
scheduleBoundaryScans(loaded);
|
|
485
|
-
(0, storageController_1.broadcastRoutingChanged)();
|
|
486
|
-
return;
|
|
487
|
-
}
|
|
488
|
-
console.log(`Rebuilding the stores for bucket ${key} (${reason}): structure changed from ${loaded.structureKey} to ${plan.structureKey}`);
|
|
489
|
-
for (let s of loaded.stores) {
|
|
490
|
-
if (s.store instanceof blobStore_1.BlobStore) {
|
|
491
|
-
await s.store.dispose();
|
|
187
|
+
}, () => {
|
|
188
|
+
if (buckets.get(key) === loaded) {
|
|
189
|
+
buckets.delete(key);
|
|
492
190
|
}
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
191
|
+
});
|
|
192
|
+
return await loaded;
|
|
193
|
+
}
|
|
194
|
+
exports.reloadBucket = reloadBucket;
|
|
195
|
+
/**
|
|
196
|
+
* Writing the routing config is a write like any other: it goes into a store, and the store applies
|
|
197
|
+
* it to itself and lets its peers pull it. The only thing that happens here is picking WHICH store,
|
|
198
|
+
* because the writer names a source and a source names a store.
|
|
199
|
+
*
|
|
200
|
+
* In-flight switchover windows are re-injected first (see intermediateManagement): an operator's
|
|
201
|
+
* config knows nothing about a switchover that is happening right now, and writing it as-is would
|
|
202
|
+
* cancel it mid-flight.
|
|
203
|
+
*/
|
|
204
|
+
async function writeRoutingConfig(account, bucketName, name, data, config) {
|
|
205
|
+
var _a;
|
|
500
206
|
(0, serverConfig_1.assertWritesAllowed)();
|
|
501
|
-
let
|
|
502
|
-
let run = (routingWrites.get(key) || Promise.resolve()).then(() => writeRoutingConfig(account, bucketName, data, config));
|
|
503
|
-
routingWrites.set(key, run.then(() => { }, () => { }));
|
|
504
|
-
return await run;
|
|
505
|
-
}
|
|
506
|
-
exports.queueRoutingConfigWrite = queueRoutingConfigWrite;
|
|
507
|
-
async function writeRoutingConfig(account, bucketName, data, config) {
|
|
508
|
-
let key = `${account}/${bucketName}`;
|
|
207
|
+
let store = getStore(account, bucketName, name);
|
|
509
208
|
let incoming = (0, remoteConfig_1.parseRoutingData)(data);
|
|
510
|
-
let
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
return;
|
|
517
|
-
}
|
|
518
|
-
if (JSON.stringify(incoming) !== loaded.routingJSON && (0, remoteConfig_1.getConfigVersion)(incoming) <= (0, remoteConfig_1.getConfigVersion)(loaded.routing)) {
|
|
519
|
-
let message = `Cannot update routing config for bucket ${key}: the new config differs from the current one but its version (${(0, remoteConfig_1.getConfigVersion)(incoming)}) is not greater than the current version (${(0, remoteConfig_1.getConfigVersion)(loaded.routing)}). Increment the version to update it. Current: ${loaded.routingJSON}. Attempted: ${JSON.stringify(incoming)}`;
|
|
520
|
-
console.error(message);
|
|
521
|
-
throw new Error(message);
|
|
522
|
-
}
|
|
523
|
-
let stored = incoming;
|
|
524
|
-
let reinjected = 0;
|
|
525
|
-
for (let intermediate of (0, intermediateSources_1.getIntermediateSources)((0, intermediateSources_1.expireIntermediateSources)(loaded.routing, Date.now()))) {
|
|
526
|
-
stored = (0, intermediateSources_1.injectIntermediateSource)(stored, {
|
|
527
|
-
splitUrl: intermediate.intermediate || intermediate.url,
|
|
528
|
-
intermediateUrl: intermediate.url,
|
|
529
|
-
start: intermediate.validWindow[0],
|
|
530
|
-
end: intermediate.validWindow[1],
|
|
531
|
-
});
|
|
532
|
-
reinjected++;
|
|
533
|
-
}
|
|
534
|
-
if (JSON.stringify(stored) !== JSON.stringify(incoming)) {
|
|
535
|
-
console.log(`Re-injected ${reinjected} in-flight switchover windows into the incoming routing config for bucket ${key} (version ${(0, remoteConfig_1.getConfigVersion)(incoming)})`);
|
|
536
|
-
}
|
|
537
|
-
// Written straight into the plain bucket folder: the routing file defines the per-route stores, so it never flows through them
|
|
538
|
-
await resolveSourceArchives((0, bucketDisk_1.getBucketFolder)(account, bucketName)).set(remoteConfig_1.ROUTING_FILE, Buffer.from((0, remoteConfig_1.serializeRemoteConfig)(stored)), { lastModified: config === null || config === void 0 ? void 0 : config.lastModified });
|
|
539
|
-
await scheduleRoutingReload(account, bucketName);
|
|
209
|
+
let current = (_a = (await getLoadedBucket(account, bucketName))) === null || _a === void 0 ? void 0 : _a.routing;
|
|
210
|
+
let stored = (0, intermediateManagement_1.reinjectIntermediates)(current, incoming);
|
|
211
|
+
await store.set({ path: remoteConfig_1.ROUTING_FILE, data: Buffer.from((0, remoteConfig_1.serializeRemoteConfig)(stored)), lastModified: config === null || config === void 0 ? void 0 : config.lastModified });
|
|
212
|
+
// The write may have CREATED the store (a new name gets a new folder), and the loaded bucket is a snapshot of the disk - so it is re-read, or every data write naming the new store is rejected until a restart
|
|
213
|
+
await reloadBucket(account, bucketName);
|
|
214
|
+
(0, storageController_1.broadcastRoutingChanged)();
|
|
540
215
|
}
|
|
216
|
+
exports.writeRoutingConfig = writeRoutingConfig;
|
|
541
217
|
/** Which buckets this process currently has loaded - what a deploy successor asks its predecessor for, so it activates exactly the buckets that are actually in use. */
|
|
542
218
|
function getActiveBucketKeys() {
|
|
543
219
|
return [...buckets.keys()].map(key => {
|
|
@@ -546,151 +222,11 @@ function getActiveBucketKeys() {
|
|
|
546
222
|
});
|
|
547
223
|
}
|
|
548
224
|
exports.getActiveBucketKeys = getActiveBucketKeys;
|
|
549
|
-
async function rebuildAllLoadedBuckets() {
|
|
550
|
-
for (let key of [...buckets.keys()]) {
|
|
551
|
-
let slash = key.indexOf("/");
|
|
552
|
-
await scheduleRoutingReload(key.slice(0, slash), key.slice(slash + 1), { force: true, reason: "all loaded buckets were asked to rebuild" });
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
exports.rebuildAllLoadedBuckets = rebuildAllLoadedBuckets;
|
|
556
|
-
const OWN_CONFIG_WRITE_THROTTLE = 30 * 1000;
|
|
557
|
-
const INTERMEDIATE_MAINTAIN_INTERVAL = 60 * 1000;
|
|
558
|
-
// Per bucket, not global: a switchover has to write every bucket's windows at once, and a shared throttle would let only one bucket through per interval
|
|
559
|
-
const lastOwnConfigWrite = new Map();
|
|
560
|
-
async function writeOwnRoutingConfig(loaded, updated, reason) {
|
|
561
|
-
let key = `${loaded.account}/${loaded.bucketName}`;
|
|
562
|
-
let sinceLast = Date.now() - (lastOwnConfigWrite.get(key) || 0);
|
|
563
|
-
if (sinceLast < OWN_CONFIG_WRITE_THROTTLE) {
|
|
564
|
-
console.log(`Not writing our own routing config update for bucket ${key} (${reason}): the last one was ${sinceLast}ms ago, under the ${OWN_CONFIG_WRITE_THROTTLE}ms throttle. Retrying on the next maintenance pass. Wanted: ${JSON.stringify(updated)}`);
|
|
565
|
-
return;
|
|
566
|
-
}
|
|
567
|
-
lastOwnConfigWrite.set(key, Date.now());
|
|
568
|
-
let version = (0, intermediateSources_1.nextIntermediateVersion)((0, remoteConfig_1.getConfigVersion)(loaded.routing));
|
|
569
|
-
let next = { ...updated, version };
|
|
570
|
-
console.log(`Writing ${remoteConfig_1.ROUTING_FILE} for bucket ${key} (${reason}), version ${(0, remoteConfig_1.getConfigVersion)(loaded.routing)} -> ${version}: ${JSON.stringify(next)}`);
|
|
571
|
-
let data = Buffer.from((0, remoteConfig_1.serializeRemoteConfig)(next));
|
|
572
|
-
await queueRoutingConfigWrite(loaded.account, loaded.bucketName, data);
|
|
573
|
-
await propagateRoutingConfig(loaded, next, data);
|
|
574
|
-
}
|
|
575
|
-
async function propagateRoutingConfig(loaded, next, data) {
|
|
576
|
-
var _a;
|
|
577
|
-
let targets = new Map();
|
|
578
|
-
for (let source of [...loaded.routing.sources, ...next.sources]) {
|
|
579
|
-
if (typeof source === "string" || source.intermediate)
|
|
580
|
-
continue;
|
|
581
|
-
if (source.type === "remote") {
|
|
582
|
-
let parsed = (0, remoteConfig_1.parseHostedUrl)(source.url);
|
|
583
|
-
if (parsed.account !== loaded.account || parsed.bucketName !== loaded.bucketName)
|
|
584
|
-
continue;
|
|
585
|
-
}
|
|
586
|
-
if (targets.has(source.url))
|
|
587
|
-
continue;
|
|
588
|
-
targets.set(source.url, source);
|
|
589
|
-
}
|
|
590
|
-
for (let [url, source] of targets) {
|
|
591
|
-
try {
|
|
592
|
-
await (0, createArchives_1.createApiArchives)(source).set(remoteConfig_1.ROUTING_FILE, data);
|
|
593
|
-
console.log(`Wrote ${remoteConfig_1.ROUTING_FILE} for bucket ${loaded.account}/${loaded.bucketName} to ${url}`);
|
|
594
|
-
}
|
|
595
|
-
catch (e) {
|
|
596
|
-
console.error(`Propagating our routing config update to ${url} failed: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`);
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
async function maintainIntermediates() {
|
|
601
|
-
let { domain, port } = (0, serverConfig_1.getStorageServerConfig)();
|
|
602
|
-
let takeover = (0, deployTakeover_1.getTakeoverIntermediate)();
|
|
603
|
-
let written = [];
|
|
604
|
-
let alreadyCorrect = [];
|
|
605
|
-
let notOurs = [];
|
|
606
|
-
// ONLY buckets already in memory. A switchover must never load a bucket: loading starts its synchronization, and buckets nothing has touched (legacy ones especially) have no writes to hand off in the first place. One that does get used mid-switchover loads on that access, and the next pass gives it its window.
|
|
607
|
-
let keys = [...buckets.keys()];
|
|
608
|
-
for (let key of keys) {
|
|
609
|
-
let loadedPromise = buckets.get(key);
|
|
610
|
-
if (!loadedPromise)
|
|
611
|
-
continue;
|
|
612
|
-
let loaded = await loadedPromise.catch(() => undefined);
|
|
613
|
-
if (!loaded)
|
|
614
|
-
continue;
|
|
615
|
-
let expired = (0, intermediateSources_1.expireIntermediateSources)(loaded.routing, Date.now());
|
|
616
|
-
if (JSON.stringify(expired) !== JSON.stringify(loaded.routing)) {
|
|
617
|
-
await writeOwnRoutingConfig(loaded, expired, `switchover windows expired more than ${intermediateSources_1.INTERMEDIATE_EXPIRE_GRACE / 1000}s ago`);
|
|
618
|
-
written.push(key);
|
|
619
|
-
continue;
|
|
620
|
-
}
|
|
621
|
-
if (!takeover)
|
|
622
|
-
continue;
|
|
623
|
-
let mainUrl = loaded.routing.sources.find(x => {
|
|
624
|
-
if (typeof x === "string" || x.type !== "remote" || x.intermediate)
|
|
625
|
-
return false;
|
|
626
|
-
let parsed = (0, remoteConfig_1.parseHostedUrl)(x.url);
|
|
627
|
-
return parsed.address === domain && parsed.port === port;
|
|
628
|
-
});
|
|
629
|
-
if (!mainUrl) {
|
|
630
|
-
notOurs.push(key);
|
|
631
|
-
continue;
|
|
632
|
-
}
|
|
633
|
-
let injected = (0, intermediateSources_1.injectIntermediateSource)(loaded.routing, {
|
|
634
|
-
splitUrl: mainUrl.url,
|
|
635
|
-
intermediateUrl: (0, remoteConfig_1.replaceHostedUrlPort)(mainUrl.url, takeover.altPort),
|
|
636
|
-
start: takeover.start,
|
|
637
|
-
end: takeover.end,
|
|
638
|
-
});
|
|
639
|
-
if (JSON.stringify(injected) === JSON.stringify(loaded.routing)) {
|
|
640
|
-
alreadyCorrect.push(key);
|
|
641
|
-
continue;
|
|
642
|
-
}
|
|
643
|
-
await writeOwnRoutingConfig(loaded, injected, `we are a deploy successor: writes route to our alternate port ${takeover.altPort} from ${new Date(takeover.start).toISOString()} until our predecessor is killed at ${new Date(takeover.end).toISOString()}`);
|
|
644
|
-
written.push(key);
|
|
645
|
-
}
|
|
646
|
-
if (!takeover)
|
|
647
|
-
return;
|
|
648
|
-
if (!keys.length) {
|
|
649
|
-
console.log(`No active buckets, so no config files to write the intermediate into (a bucket is only active once something uses it)`);
|
|
650
|
-
return;
|
|
651
|
-
}
|
|
652
|
-
if (!written.length) {
|
|
653
|
-
console.log(`Wrote no config files: of ${keys.length} active buckets, ${alreadyCorrect.length} already contain the intermediate and ${notOurs.length} are not hosted by us`);
|
|
654
|
-
}
|
|
655
|
-
}
|
|
656
|
-
/** Our predecessor still holds the main port and has been serving all along, so it - not us - knows which buckets are in use. We activate exactly those, which is what makes their config files get the intermediate; nothing else on disk is touched. */
|
|
657
|
-
async function activatePredecessorBuckets() {
|
|
658
|
-
var _a, _b;
|
|
659
|
-
let { domain, port } = (0, serverConfig_1.getStorageServerConfig)();
|
|
660
|
-
let url = `https://${domain}:${port}`;
|
|
661
|
-
let keys;
|
|
662
|
-
try {
|
|
663
|
-
keys = await (0, createArchives_1.listServerActiveBucketKeys)({ url });
|
|
664
|
-
}
|
|
665
|
-
catch (e) {
|
|
666
|
-
console.error(`Could not ask our predecessor on ${url} which buckets are active, so only buckets used on this process get the intermediate: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`);
|
|
667
|
-
return;
|
|
668
|
-
}
|
|
669
|
-
if (!keys.length) {
|
|
670
|
-
console.log(`Our predecessor on ${url} has no active buckets, so there are no config files to write the intermediate into`);
|
|
671
|
-
return;
|
|
672
|
-
}
|
|
673
|
-
console.log(`Our predecessor on ${url} has ${keys.length} active buckets, activating them here so their config files get the intermediate: ${keys.map(x => `${x.account}/${x.bucketName}`).join(", ")}`);
|
|
674
|
-
for (let { account, bucketName } of keys) {
|
|
675
|
-
try {
|
|
676
|
-
await getLoadedBucket(account, bucketName);
|
|
677
|
-
}
|
|
678
|
-
catch (e) {
|
|
679
|
-
console.error(`Activating bucket ${account}/${bucketName} (active on our predecessor) failed: ${(_b = e.stack) !== null && _b !== void 0 ? _b : e}`);
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
/** Started by deployTakeover once we are actually a deploy successor listening on an alternate port. Until then there are no switchover windows to write or expire, so nothing polls. */
|
|
684
|
-
exports.startIntermediateMaintenance = (0, caching_1.lazy)(() => {
|
|
685
|
-
void (async () => {
|
|
686
|
-
await activatePredecessorBuckets();
|
|
687
|
-
await maintainIntermediates();
|
|
688
|
-
})().catch((e) => { var _a; return console.error(`Writing the intermediate into the config files failed: ${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`); });
|
|
689
|
-
(0, batching_1.runInfinitePoll)(INTERMEDIATE_MAINTAIN_INTERVAL, maintainIntermediates);
|
|
690
|
-
});
|
|
691
225
|
function toActiveBucketInfo(loaded) {
|
|
226
|
+
var _a;
|
|
692
227
|
return {
|
|
693
|
-
folder
|
|
228
|
+
// One of its stores' folders - a bucket no longer has a folder of its own, it has one per store
|
|
229
|
+
folder: ((_a = loaded.stores[0]) === null || _a === void 0 ? void 0 : _a.folder) || "",
|
|
694
230
|
routing: loaded.routing,
|
|
695
231
|
selfEntries: loaded.selfEntries,
|
|
696
232
|
self: loaded.self,
|
|
@@ -698,7 +234,7 @@ function toActiveBucketInfo(loaded) {
|
|
|
698
234
|
};
|
|
699
235
|
}
|
|
700
236
|
/** The live in-memory state of ONE bucket, answered without touching the disk (no routing file read, no statfs, no stored write stats). Returns an error string when the bucket is not loaded here, which is the normal state for a bucket nothing has accessed since startup. */
|
|
701
|
-
async function
|
|
237
|
+
async function debugGetActiveBucket(account, bucketName) {
|
|
702
238
|
var _a;
|
|
703
239
|
let key = `${account}/${bucketName}`;
|
|
704
240
|
let loadedPromise = buckets.get(key);
|
|
@@ -717,7 +253,7 @@ async function getActiveBucket(account, bucketName) {
|
|
|
717
253
|
}
|
|
718
254
|
return toActiveBucketInfo(loaded);
|
|
719
255
|
}
|
|
720
|
-
exports.
|
|
256
|
+
exports.debugGetActiveBucket = debugGetActiveBucket;
|
|
721
257
|
/** Loads a bucket that exists on this server's disk into memory, which starts its synchronization and window timers, and returns its live state. Nothing is written and no other server is contacted - unlike building an ArchivesChain for it, which would probe every source and could write the routing config. Already-loaded buckets just return their state. */
|
|
722
258
|
async function activateBucket(account, bucketName) {
|
|
723
259
|
var _a;
|
|
@@ -731,13 +267,11 @@ async function activateBucket(account, bucketName) {
|
|
|
731
267
|
return `Bucket ${key} failed to load on this server: ${String((_a = e.stack) !== null && _a !== void 0 ? _a : e).slice(0, 500)}`;
|
|
732
268
|
}
|
|
733
269
|
if (!loaded) {
|
|
734
|
-
return `Bucket ${key} does not exist on this server (no
|
|
270
|
+
return `Bucket ${key} does not exist on this server (it has no store folders under ${(0, bucketDisk_1.getBucketFolder)("<name>", account, bucketName)})`;
|
|
735
271
|
}
|
|
736
272
|
// Wait for the indexes to load, so the totals we return are the real ones rather than zeroes from stores that have not read their index yet. The source scans keep running in the background.
|
|
737
273
|
for (let s of loaded.stores) {
|
|
738
|
-
|
|
739
|
-
await s.store.init();
|
|
740
|
-
}
|
|
274
|
+
await s.store.init();
|
|
741
275
|
}
|
|
742
276
|
if (!wasLoaded) {
|
|
743
277
|
console.log(`Activated bucket ${key} on request: it is now loaded and synchronizing`);
|
|
@@ -745,7 +279,7 @@ async function activateBucket(account, bucketName) {
|
|
|
745
279
|
return toActiveBucketInfo(loaded);
|
|
746
280
|
}
|
|
747
281
|
exports.activateBucket = activateBucket;
|
|
748
|
-
async function
|
|
282
|
+
async function debugListAccountBuckets(account) {
|
|
749
283
|
let start = Date.now();
|
|
750
284
|
let timings = new Map();
|
|
751
285
|
async function timed(name, run) {
|
|
@@ -757,21 +291,20 @@ async function listAccountBuckets(account) {
|
|
|
757
291
|
timings.set(name, (timings.get(name) || 0) + (Date.now() - began));
|
|
758
292
|
}
|
|
759
293
|
}
|
|
760
|
-
|
|
761
|
-
let
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
294
|
+
// The disk is the record: a bucket exists here when it has at least one store folder, and several names for one bucket are still one bucket
|
|
295
|
+
let folders = await timed("readdir", () => (0, bucketDisk_1.listAccountStoreFolders)(account));
|
|
296
|
+
let byBucket = new Map();
|
|
297
|
+
for (let store of folders) {
|
|
298
|
+
if (byBucket.has(store.bucketName))
|
|
299
|
+
continue;
|
|
300
|
+
byBucket.set(store.bucketName, store.folder);
|
|
767
301
|
}
|
|
768
|
-
|
|
769
|
-
names = [...new Set(names.map(x => x.replace(/-route-[\d.]+-[\d.]+$/, "")))];
|
|
302
|
+
let names = [...byBucket.keys()];
|
|
770
303
|
try {
|
|
771
304
|
return await Promise.all(names.map(async (bucketName) => {
|
|
772
305
|
var _a, _b;
|
|
773
306
|
let key = `${account}/${bucketName}`;
|
|
774
|
-
let folder =
|
|
307
|
+
let folder = byBucket.get(bucketName) || "";
|
|
775
308
|
let base = { bucketName, active: false, folder };
|
|
776
309
|
base.disk = await timed("statfs", () => (0, bucketDisk_1.getDiskInfo)(folder)).catch((e) => {
|
|
777
310
|
var _a;
|
|
@@ -792,11 +325,10 @@ async function listAccountBuckets(account) {
|
|
|
792
325
|
}
|
|
793
326
|
}
|
|
794
327
|
try {
|
|
795
|
-
const
|
|
796
|
-
if (!
|
|
797
|
-
return { ...base, error: `No routing file (${remoteConfig_1.ROUTING_FILE})` };
|
|
328
|
+
const parsed = await timed("readRoutingFile", () => (0, bucketDisk_1.readRoutingFromDisk)(account, bucketName));
|
|
329
|
+
if (!parsed) {
|
|
330
|
+
return { ...base, error: `No routing file (${remoteConfig_1.ROUTING_FILE}) in any of its stores` };
|
|
798
331
|
}
|
|
799
|
-
let parsed = await timed("parseRouting", async () => (0, remoteConfig_1.parseRoutingData)(data));
|
|
800
332
|
return { ...base, config: { remoteConfig: parsed } };
|
|
801
333
|
}
|
|
802
334
|
catch (e) {
|
|
@@ -807,10 +339,10 @@ async function listAccountBuckets(account) {
|
|
|
807
339
|
finally {
|
|
808
340
|
// The parts run concurrently, so these are summed wall times per part, not a breakdown of the total
|
|
809
341
|
let parts = [...timings].map(([name, ms]) => `${name} ${ms}ms`).join(", ");
|
|
810
|
-
console.log(`
|
|
342
|
+
console.log(`debugListAccountBuckets(${account}) took ${Date.now() - start}ms for ${names.length} buckets: ${parts}`);
|
|
811
343
|
}
|
|
812
344
|
}
|
|
813
|
-
exports.
|
|
345
|
+
exports.debugListAccountBuckets = debugListAccountBuckets;
|
|
814
346
|
function emptyWriteStats() {
|
|
815
347
|
return { originalWrites: 0, originalBytes: 0, flushedWrites: 0, flushedBytes: 0 };
|
|
816
348
|
}
|
|
@@ -835,7 +367,7 @@ function getBucketWriteStats(key) {
|
|
|
835
367
|
return writeStats.get(key) || emptyWriteStats();
|
|
836
368
|
}
|
|
837
369
|
/** Zeroes the write statistics of every bucket in the account. */
|
|
838
|
-
function
|
|
370
|
+
function debugClearAccountWriteStats(account) {
|
|
839
371
|
let prefix = `${account}/`;
|
|
840
372
|
let cleared = 0;
|
|
841
373
|
for (let key of [...writeStats.keys()]) {
|
|
@@ -847,107 +379,6 @@ function clearAccountWriteStats(account) {
|
|
|
847
379
|
console.log(`Cleared the write statistics of ${cleared} buckets in account ${account}`);
|
|
848
380
|
return cleared;
|
|
849
381
|
}
|
|
850
|
-
exports.
|
|
851
|
-
const LARGE_FILE_PART_SIZE = 8 * 1024 * 1024;
|
|
852
|
-
|
|
853
|
-
class BucketIArchivesWrapper {
|
|
854
|
-
constructor(account, bucketName, sourceConfig) {
|
|
855
|
-
this.account = account;
|
|
856
|
-
this.bucketName = bucketName;
|
|
857
|
-
this.sourceConfig = sourceConfig;
|
|
858
|
-
}
|
|
859
|
-
findStore() {
|
|
860
|
-
return findBucketStore(this.account, this.bucketName, this.sourceConfig);
|
|
861
|
-
}
|
|
862
|
-
getDebugName() {
|
|
863
|
-
return `localBucket account ${this.account} bucket ${this.bucketName} route ${JSON.stringify(this.sourceConfig.route || IArchives_1.FULL_ROUTE)}`;
|
|
864
|
-
}
|
|
865
|
-
async get(fileName, config) {
|
|
866
|
-
let result = await this.get2(fileName, config);
|
|
867
|
-
return result && result.data || undefined;
|
|
868
|
-
}
|
|
869
|
-
async get2(fileName, config) {
|
|
870
|
-
if (fileName === remoteConfig_1.ROUTING_FILE) {
|
|
871
|
-
return await (0, bucketDisk_1.getRoutingFileResult)(this.account, this.bucketName);
|
|
872
|
-
}
|
|
873
|
-
if (config === null || config === void 0 ? void 0 : config.internal) {
|
|
874
|
-
return await readBucketInternal(this.account, this.bucketName, { path: fileName, range: config.range, includeTombstones: config.includeTombstones });
|
|
875
|
-
}
|
|
876
|
-
return await (await this.findStore()).store.get2({ path: fileName, ...config });
|
|
877
|
-
}
|
|
878
|
-
async set(fileName, data, config) {
|
|
879
|
-
(0, serverConfig_1.assertWritesAllowed)();
|
|
880
|
-
if (fileName === remoteConfig_1.ROUTING_FILE) {
|
|
881
|
-
await queueRoutingConfigWrite(this.account, this.bucketName, data, config);
|
|
882
|
-
return fileName;
|
|
883
|
-
}
|
|
884
|
-
await (await this.findStore()).store.set({ ...config, path: fileName, data });
|
|
885
|
-
return fileName;
|
|
886
|
-
}
|
|
887
|
-
async del(fileName, config) {
|
|
888
|
-
(0, serverConfig_1.assertWritesAllowed)();
|
|
889
|
-
await (await this.findStore()).store.del({ path: fileName, ...config });
|
|
890
|
-
}
|
|
891
|
-
async setLargeFile(config) {
|
|
892
|
-
(0, serverConfig_1.assertWritesAllowed)();
|
|
893
|
-
let store = (await this.findStore()).store;
|
|
894
|
-
let id = await store.startLargeUpload({ path: config.path, lastModified: config.lastModified });
|
|
895
|
-
try {
|
|
896
|
-
while (true) {
|
|
897
|
-
let data = await config.getNextData();
|
|
898
|
-
if (!data)
|
|
899
|
-
break;
|
|
900
|
-
for (let offset = 0; offset < data.length; offset += LARGE_FILE_PART_SIZE) {
|
|
901
|
-
await store.appendLargeUpload({ id, data: data.subarray(offset, offset + LARGE_FILE_PART_SIZE) });
|
|
902
|
-
}
|
|
903
|
-
}
|
|
904
|
-
await store.finishLargeUpload({ id, path: config.path, lastModified: config.lastModified });
|
|
905
|
-
}
|
|
906
|
-
catch (e) {
|
|
907
|
-
await store.cancelLargeUpload({ id });
|
|
908
|
-
throw e;
|
|
909
|
-
}
|
|
910
|
-
}
|
|
911
|
-
async getInfo(fileName, config) {
|
|
912
|
-
if (fileName === remoteConfig_1.ROUTING_FILE) {
|
|
913
|
-
let result = await (0, bucketDisk_1.getRoutingFileResult)(this.account, this.bucketName);
|
|
914
|
-
return result && { writeTime: result.writeTime, size: result.size } || undefined;
|
|
915
|
-
}
|
|
916
|
-
return await (await this.findStore()).store.getInfo({ path: fileName, ...config });
|
|
917
|
-
}
|
|
918
|
-
async findInfo(prefix, config) {
|
|
919
|
-
return await (await this.findStore()).store.findInfo({ prefix, ...config });
|
|
920
|
-
}
|
|
921
|
-
async find(prefix, config) {
|
|
922
|
-
return (await this.findInfo(prefix, config)).map(x => x.path);
|
|
923
|
-
}
|
|
924
|
-
async getURL(filePath) {
|
|
925
|
-
let { domain, port } = (0, serverConfig_1.getStorageServerConfig)();
|
|
926
|
-
return (0, remoteConfig_1.buildFileUrl)(`https://${domain}:${port}/file/${encodeURIComponent(this.account)}/${encodeURIComponent(this.bucketName)}`, filePath);
|
|
927
|
-
}
|
|
928
|
-
async getConfig() {
|
|
929
|
-
return getBucketConfig(await requireBucket(this.account, this.bucketName));
|
|
930
|
-
}
|
|
931
|
-
async hasWriteAccess() {
|
|
932
|
-
return true;
|
|
933
|
-
}
|
|
934
|
-
async getChangesAfter2(config) {
|
|
935
|
-
return await (await this.findStore()).store.getChangesAfter2(config);
|
|
936
|
-
}
|
|
937
|
-
async getSyncStatus() {
|
|
938
|
-
return await bucketSyncStatus(await requireBucket(this.account, this.bucketName));
|
|
939
|
-
}
|
|
940
|
-
}
|
|
941
|
-
const localArchives = new Map();
|
|
942
|
-
function getLocalArchives(account, bucketName, sourceConfig) {
|
|
943
|
-
let key = `${account}/${bucketName}|${stableStringify(sourceConfig)}`;
|
|
944
|
-
let existing = localArchives.get(key);
|
|
945
|
-
if (existing)
|
|
946
|
-
return existing;
|
|
947
|
-
let archives = new BucketIArchivesWrapper(account, bucketName, sourceConfig);
|
|
948
|
-
localArchives.set(key, archives);
|
|
949
|
-
return archives;
|
|
950
|
-
}
|
|
951
|
-
exports.getLocalArchives = getLocalArchives;
|
|
952
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmFnZVNlcnZlclN0YXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3RvcmFnZVNlcnZlclN0YXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLGdEQUF3QjtBQUN4Qiw0Q0FBb0I7QUFDcEIseURBQW1EO0FBQ25ELG1EQUFnRDtBQUNoRCwyREFBK0Q7QUFDL0Qsa0RBQStDO0FBQy9DLDJDQUF1SDtBQUN2SCw0Q0FHc0I7QUFDdEIsaURBQWlNO0FBQ2pNLCtEQUF3SztBQUN4SyxxREFBMkQ7QUFDM0QscURBQWlGO0FBQ2pGLDJEQUE4RDtBQUM5RCxpREFBNkU7QUFDN0UsNkNBQXdJO0FBQ3hJLDJDQUF3RztBQTBCeEcsbUxBQW1MO0FBQ25MLFNBQVMsZUFBZSxDQUFDLEtBQWM7SUFDbkMsSUFBSSxDQUFDLEtBQUssSUFBSSxPQUFPLEtBQUssS0FBSyxRQUFRO1FBQUUsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3RFLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ3ZCLE9BQU8sSUFBSSxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUM7SUFDL0QsQ0FBQztJQUNELElBQUksT0FBTyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsS0FBZ0MsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxTQUFTLENBQUMsQ0FBQztJQUMvRixJQUFBLFdBQUksRUFBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN6QixPQUFPLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxF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QVUsQ0FBQyxDQUFDLENBQUM7SUFDdEYsQ0FBQztDQUNKO0FBRUQsTUFBTSxhQUFhLEdBQUcsSUFBSSxHQUFHLEVBQXFCLENBQUM7QUFDbkQsU0FBZ0IsZ0JBQWdCLENBQUMsT0FBZSxFQUFFLFVBQWtCLEVBQUUsWUFBMEI7SUFDNUYsSUFBSSxHQUFHLEdBQUcsR0FBRyxPQUFPLElBQUksVUFBVSxJQUFJLGVBQWUsQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDO0lBQ3RFLElBQUksUUFBUSxHQUFHLGFBQWEsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdEMsSUFBSSxRQUFRO1FBQUUsT0FBTyxRQUFRLENBQUM7SUFDOUIsSUFBSSxRQUFRLEdBQUcsSUFBSSxzQkFBc0IsQ0FBQyxPQUFPLEVBQUUsVUFBVSxFQUFFLFlBQVksQ0FBQyxDQUFDO0lBQzdFLGFBQWEsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQ2pDLE9BQU8sUUFBUSxDQUFDO0FBQ3BCLENBQUM7QUFQRCw0Q0FPQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBwYXRoIGZyb20gXCJwYXRoXCI7XG5pbXBvcnQgZnMgZnJvbSBcImZzXCI7XG5pbXBvcnQgeyBsYXp5IH0gZnJvbSBcInNvY2tldC1mdW5jdGlvbi9zcmMvY2FjaGluZ1wiO1xuaW1wb3J0IHsgc29ydCB9IGZyb20gXCJzb2NrZXQtZnVuY3Rpb24vc3JjL21pc2NcIjtcbmltcG9ydCB7IHJ1bkluZmluaXRlUG9sbCB9IGZyb20gXCJzb2NrZXQtZnVuY3Rpb24vc3JjL2JhdGNoaW5nXCI7XG5pbXBvcnQgeyBBcmNoaXZlc0Rpc2sgfSBmcm9tIFwiLi4vQXJjaGl2ZXNEaXNrXCI7XG5pbXBvcnQgeyBCbG9iU3RvcmUsIFJhd0Rpc2tTdG9yZSwgSUJ1Y2tldFN0b3JlLCBERUZBVUxUX0ZBU1RfV1JJVEVfREVMQVksIFdJTkRPV19FTkRfRkxVU0hfTUFSR0lOIH0gZnJvbSBcIi4vYmxvYlN0b3JlXCI7XG5pbXBvcnQge1xuICAgIFJlbW90ZUNvbmZpZywgSG9zdGVkQ29uZmlnLCBTb3VyY2VDb25maWcsIElBcmNoaXZlcywgQXJjaGl2ZXNTb3VyY2UsIEFyY2hpdmVzQ29uZmlnLCBBcmNoaXZlc1N5bmNTdGF0dXMsXG4gICAgQXJjaGl2ZUZpbGVJbmZvLCBDaGFuZ2VzQWZ0ZXJDb25maWcsIERlbENvbmZpZywgRmluZENvbmZpZywgR2V0Q29uZmlnLCBHZXRJbmZvQ29uZmlnLCBTZXRDb25maWcsIFN5bmNBY3Rpdml0eSwgRlVMTF9ST1VURSxcbn0gZnJvbSBcIi4uL0lBcmNoaXZlc1wiO1xuaW1wb3J0IHsgUk9VVElOR19GSUxFLCBwYXJzZVJvdXRpbmdEYXRhLCBzZXJpYWxpemVSZW1vdGVDb25maWcsIHBhcnNlSG9zdGVkVXJsLCByZXBsYWNlSG9zdGVkVXJsUG9ydCwgYnVpbGRGaWxlVXJsLCBnZXRDb25maWdWZXJzaW9uLCByb3V0ZUludGVyc2VjdGlvbiwgbm9ybWFsaXplU291cmNlIH0gZnJvbSBcIi4vcmVtb3RlQ29uZmlnXCI7XG5pbXBvcnQgeyBpbmplY3RJbnRlcm1lZGlhdGVTb3VyY2UsIGV4cGlyZUludGVybWVkaWF0ZVNvdXJjZXMsIGdldEludGVybWVkaWF0ZVNvdXJjZXMsIG5leHRJbnRlcm1lZGlhdGVWZXJzaW9uLCBJTlRFUk1FRElBVEVfRVhQSVJFX0dSQUNFIH0gZnJvbSBcIi4vaW50ZXJtZWRpYXRlU291cmNlc1wiO1xuaW1wb3J0IHsgZ2V0VGFrZW92ZXJJbnRlcm1lZGlhdGUgfSBmcm9tIFwiLi9kZXBsb3lUYWtlb3ZlclwiO1xuaW1wb3J0IHsgY3JlYXRlQXBpQXJjaGl2ZXMsIGxpc3RTZXJ2ZXJBY3RpdmVCdWNrZXRLZXlzIH0gZnJvbSBcIi4vY3JlYXRlQXJjaGl2ZXNcIjtcbmltcG9ydCB7IGJyb2FkY2FzdFJvdXRpbmdDaGFuZ2VkIH0gZnJvbSBcIi4vc3RvcmFnZUNvbnRyb2xsZXJcIjtcbmltcG9ydCB7IGdldFN0b3JhZ2VTZXJ2ZXJDb25maWcsIGFzc2VydFdyaXRlc0FsbG93ZWQgfSBmcm9tIFwiLi9zZXJ2ZXJDb25maWdcIjtcbmltcG9ydCB7IGdldEJ1Y2tldEZvbGRlciwgcmVhZFJvdXRpbmdGaWxlLCByZWFkUm91dGluZ0Zyb21EaXNrLCBnZXRSb3V0aW5nRmlsZVJlc3VsdCwgZ2V0RGlza0luZm8sIEJ1Y2tldERpc2tJbmZvIH0gZnJvbSBcIi4vYnVja2V0RGlza1wiO1xuaW1wb3J0IHsgY29tcHV0ZVN0b3JlUGxhbiwgZmluZFNlbGZJbmRleGVzLCBTdG9yZVBsYW4sIFN0b3JlUGxhblN0b3JlLCBTZWxmU3VtbWFyeSB9IGZyb20gXCIuL3N0b3JlUGxhblwiO1xuXG4vLyBUaGUgc3RvcmFnZSBzZXJ2ZXIncyBidWNrZXQgbGlmZWN5Y2xlOiB0aGUgbWFwIG9mIGxvYWRlZCBidWNrZXRzIChlYWNoID0gaXRzIHJvdXRpbmcgY29uZmlnICsgb25lIEJsb2JTdG9yZSBwZXIgcm91dGUpLCBrZWVwaW5nIHRoZW0gY3VycmVudCAocm91dGluZyByZWxvYWRzLCB3aW5kb3ctYm91bmRhcnkgcmVidWlsZHMsIGJvdW5kYXJ5IHNjYW5zKSwgd3JpdGluZy9wcm9wYWdhdGluZyByb3V0aW5nIGNvbmZpZ3MsIGRlcGxveS1zd2l0Y2hvdmVyIG1haW50ZW5hbmNlLCBhbmQgdGhlIHNlcnZlci1sZXZlbCBidWNrZXQgbGlzdGluZ3MuIFN0b3JlIHNlbGVjdGlvbiAoc291cmNlQ29uZmlnIC0+IHN0b3JlKSBsaXZlcyBoZXJlIHRvbywgYXMgZmluZEJ1Y2tldFN0b3JlLlxuXG5leHBvcnQgdHlwZSBMb2FkZWRTdG9yZSA9IHtcbiAgICAvLyBKU09OIG9mIHRoZSByb3V0ZSAoRlVMTF9ST1VURSB3aGVuIGFic2VudCkgLSB0aGUgT05FIHJvdXRlIHRoaXMgc3RvcmUgc2VydmVzXG4gICAgcm91dGVLZXk6IHN0cmluZztcbiAgICByb3V0ZT86IFtudW1iZXIsIG51bWJlcl07XG4gICAgLy8gVGhlIGV4YWN0IHNlbGYgZW50cmllcyB0aGlzIHN0b3JlIHNlcnZlcyAoc2FtZSByb3V0ZSwgZGlmZmVyZW50IHZhbGlkIHdpbmRvd3MpLiBFbXB0eSB3aGVuIHdlIGFyZSBub3QgaW4gdGhlIGNvbmZpZyBidXQgc3RpbGwgc2VydmUgb3VyIGRpc2sgZGF0YS5cbiAgICBlbnRyaWVzOiBIb3N0ZWRDb25maWdbXTtcbiAgICBmb2xkZXI6IHN0cmluZztcbiAgICBzdG9yZTogSUJ1Y2tldFN0b3JlO1xufTtcblxuLy8gQSBidWNrZXQgbG9hZGVkIG9uIHRoaXMgc2VydmVyOiBpdHMgcm91dGluZyBjb25maWcgYW5kIGl0cyBwZXItcm91dGUgc3RvcmVzLiBQdXJlIGRhdGEgLSB0aGUgc3RvcmVzIHRoZW1zZWx2ZXMgZG8gdGhlIHdvcmsuXG5leHBvcnQgdHlwZSBCdWNrZXRTdGF0ZSA9IHtcbiAgICBhY2NvdW50OiBzdHJpbmc7XG4gICAgYnVja2V0TmFtZTogc3RyaW5nO1xuICAgIHJvdXRpbmc6IFJlbW90ZUNvbmZpZztcbiAgICByb3V0aW5nSlNPTjogc3RyaW5nO1xuICAgIHNlbGZFbnRyaWVzOiBIb3N0ZWRDb25maWdbXTtcbiAgICBzZWxmOiBTZWxmU3VtbWFyeSB8IHVuZGVmaW5lZDtcbiAgICBzdG9yZXM6IExvYWRlZFN0b3JlW107XG4gICAgc3RydWN0dXJlS2V5OiBzdHJpbmc7XG59O1xuXG4vKiogSlNPTiB3aXRoIHNvcnRlZCBvYmplY3Qga2V5cyBhbmQgdW5kZWZpbmVkLXZhbHVlZCBrZXlzIGRyb3BwZWQsIHNvIHR3byBjb25maWdzIHRoYXQgbWVhbiB0aGUgc2FtZSB0aGluZyBjb21wYXJlIGVxdWFsIHJlZ2FyZGxlc3Mgb2Yga2V5IG9yZGVyIG9yIHdoaWNoIHNpZGUgc2VyaWFsaXplZCB0aGVtLiAqL1xuZnVuY3Rpb24gc3RhYmxlU3RyaW5naWZ5KHZhbHVlOiB1bmtub3duKTogc3RyaW5nIHtcbiAgICBpZiAoIXZhbHVlIHx8IHR5cGVvZiB2YWx1ZSAhPT0gXCJvYmplY3RcIikgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHZhbHVlKTtcbiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIGBbJHt2YWx1ZS5tYXAoeCA9PiBzdGFibGVTdHJpbmdpZnkoeCkpLmpvaW4oXCIsXCIpfV1gO1xuICAgIH1cbiAgICBsZXQgZW50cmllcyA9IE9iamVjdC5lbnRyaWVzKHZhbHVlIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KS5maWx0ZXIoeCA9PiB4WzFdICE9PSB1bmRlZmluZWQpO1xuICAgIHNvcnQoZW50cmllcywgeCA9PiB4WzBdKTtcbiAgICByZXR1cm4gYHske2VudHJpZXMubWFwKChba2V5LCBjaGlsZF0pID0+IGAke0pTT04uc3RyaW5naWZ5KGtleSl9OiR7c3RhYmxlU3RyaW5naWZ5KGNoaWxkKX1gKS5qb2luKFwiLFwiKX19YDtcbn1cblxuLyoqIFRoZSBsb2FkZWQgYnVja2V0LCBsb2FkaW5nIGl0ICh3aGljaCBpbnN0YW50aWF0ZXMgaXRzIHN0b3JlcyBhbmQgc3RhcnRzIHRoZWlyIHN5bmNocm9uaXphdGlvbikgaWYgbmVlZGVkLiBBIGJ1Y2tldCB0aGF0IGRvZXMgbm90IGV4aXN0IG9uIHRoaXMgc2VydmVyIHRocm93cyAtIGNhbGxlcnMgbmV2ZXIgc2VlIHVuZGVmaW5lZCBidWNrZXRzLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlcXVpcmVCdWNrZXQoYWNjb3VudDogc3RyaW5nLCBidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPEJ1Y2tldFN0YXRlPiB7XG4gICAgbGV0IGJ1Y2tldCA9IGF3YWl0IGdldExvYWRlZEJ1Y2tldChhY2NvdW50LCBidWNrZXROYW1lKTtcbiAgICBpZiAoIWJ1Y2tldCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEJ1Y2tldCAke2FjY291bnR9LyR7YnVja2V0TmFtZX0gZG9lcyBub3QgZXhpc3Qgb24gdGhpcyBzZXJ2ZXIuIFdyaXRlIGl0cyByb3V0aW5nIGNvbmZpZyB0byAke0pTT04uc3RyaW5naWZ5KFJPVVRJTkdfRklMRSl9IHRvIGNyZWF0ZSBpdC5gKTtcbiAgICB9XG4gICAgcmV0dXJuIGJ1Y2tldDtcbn1cblxuLyoqIFRoZSBzdGFibGUgaWRlbnRpdHkgb2YgYSBzb3VyY2UgY29uZmlnIGZvciBtYXRjaGluZzogZXZlcnl0aGluZyBFWENFUFQgdGhlIHZhbGlkIHdpbmRvdywgYW5kIHdpdGggYW4gaW50ZXJtZWRpYXRlIHJlc29sdmVkIGJhY2sgdG8gdGhlIHNvdXJjZSBpdCB3YXMgc3BsaXQgb3V0IG9mLiBUaGUgd2luZG93IGRyaWZ0cyAoYSBzd2l0Y2hvdmVyIHNwbGl0cyBvbmUgd2luZG93IGluIHR3byBhcm91bmQgYW4gaW50ZXJtZWRpYXRlLCB0aGVuIHJlam9pbnMgaXQpLCBzbyBhIGNhbGxlciBhbmQgdGhpcyBzZXJ2ZXIgcm91dGluZWx5IGRpc2FncmVlIG9uIGl0IC0gbWF0Y2hpbmcgb24gaXQgd291bGQgd3JvbmdseSByZWplY3QgdGhlIHJlcXVlc3QuIEFuIGludGVybWVkaWF0ZSBpcyBhIHRyYW5zaWVudCBhbHQtcG9ydCB2aWV3IG9mIGFub3RoZXIgc291cmNlLCBzbyBpdCBtdXN0IHJlc29sdmUgdG8gVEhBVCBzb3VyY2UgKGNvbmZpZy5pbnRlcm1lZGlhdGUgaG9sZHMgaXRzIHVybCArIHRoZSBpbnRlcm1lZGlhdGUgZmxhZyBpcyBkcm9wcGVkKSwgb3IgYSByZXF1ZXN0IG5hbWluZyB0aGUgaW50ZXJtZWRpYXRlIHdvdWxkIGZhaWwgdG8gbWF0Y2ggb25jZSB0aGUgaW50ZXJtZWRpYXRlIGhhcyByZWpvaW5lZCBhbmQgaXRzIGVudHJ5IGlzIGdvbmUuIFRoZSByb3V0ZSBzdGF5cyBpbiB0aGUgaWRlbnRpdHkgKGl0IHNlbGVjdHMgdGhlIHN0b3JlL2ZvbGRlcikuICovXG5mdW5jdGlvbiBzb3VyY2VNYXRjaEtleShjb25maWc6IFNvdXJjZUNvbmZpZyk6IHN0cmluZyB7XG4gICAgbGV0IHVybCA9IGNvbmZpZy5pbnRlcm1lZGlhdGUgfHwgY29uZmlnLnVybDtcbiAgICByZXR1cm4gc3RhYmxlU3RyaW5naWZ5KHsgLi4uY29uZmlnLCB1cmwsIGludGVybWVkaWF0ZTogdW5kZWZpbmVkLCB2YWxpZFdpbmRvdzogdW5kZWZpbmVkIH0pO1xufVxuXG4vKiogVGhlIHN0b3JlIHNlcnZpbmcgYSByZXF1ZXN0OiB0aGUgY29uZmlnIGVudHJ5IHRoZSBDTElFTlQgc2VsZWN0ZWQsIG1hdGNoZWQgYWdhaW5zdCB0aGUgYnVja2V0J3Mgb3duIGVudHJpZXMgYnkgaWRlbnRpdHkgRVhDTFVESU5HIHRoZSB2YWxpZCB3aW5kb3cgKHNlZSBzb3VyY2VNYXRjaEtleSkuIFRoZSBzZWxlY3Rpb24gbmV2ZXIgdmFsaWRhdGVzIC0gdGhlIHN0b3JlJ3Mgb3duIHdpbmRvdy9yb3V0ZSBjaGVja3MgdGhyb3cgaWYgdGhlIGNhbGxlciBpcyBzdGFsZSAtIHNvIGhvbm9yaW5nIGEgd2luZG93IG1pc21hdGNoIGhlcmUgaXMgZXhhY3RseSByaWdodC4gVGhyb3dzIHdoZW4gbm90aGluZyBtYXRjaGVzLCBsaXN0aW5nIHdoYXQgaXMgYXZhaWxhYmxlLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGZpbmRCdWNrZXRTdG9yZShhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZywgc291cmNlQ29uZmlnOiBTb3VyY2VDb25maWcgfCB1bmRlZmluZWQpOiBQcm9taXNlPExvYWRlZFN0b3JlPiB7XG4gICAgbGV0IGJ1Y2tldCA9IGF3YWl0IHJlcXVpcmVCdWNrZXQoYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgaWYgKCFzb3VyY2VDb25maWcpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBObyByZW1vdGUgc291cmNlIGNvbmZpZ3VyYXRpb24gd2FzIHByb3ZpZGVkIGZvciBidWNrZXQgJHthY2NvdW50fS8ke2J1Y2tldE5hbWV9OiBldmVyeSByZXF1ZXN0IG11c3Qgc2F5IHdoaWNoIGNvbmZpZ3VyZWQgc291cmNlIGl0IHNlbGVjdGVkLiBBdmFpbGFibGU6ICR7SlNPTi5zdHJpbmdpZnkoYnVja2V0LnNlbGZFbnRyaWVzKX1gKTtcbiAgICB9XG4gICAgbGV0IHdhbnRlZCA9IHNvdXJjZU1hdGNoS2V5KHNvdXJjZUNvbmZpZyk7XG4gICAgZm9yIChsZXQgcyBvZiBidWNrZXQuc3RvcmVzKSB7XG4gICAgICAgIGlmIChzLmVudHJpZXMuc29tZShlID0+IHNvdXJjZU1hdGNoS2V5KGUpID09PSB3YW50ZWQpKSByZXR1cm4gcztcbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKGBObyBzb3VyY2Ugb24gdGhpcyBzZXJ2ZXIgbWF0Y2hlcyB0aGUgcmVxdWVzdGVkIHJlbW90ZSBjb25maWd1cmF0aW9uIGZvciBidWNrZXQgJHthY2NvdW50fS8ke2J1Y2tldE5hbWV9LiBSZXF1ZXN0ZWQ6ICR7SlNPTi5zdHJpbmdpZnkoc291cmNlQ29uZmlnKX0uIEF2YWlsYWJsZTogJHtKU09OLnN0cmluZ2lmeShidWNrZXQuc2VsZkVudHJpZXMpfWApO1xufVxuXG4vKiogSW50ZXJuYWwgKHN0b3JlLXRvLXN0b3JlKSByZWFkcyBza2lwIHN0b3JlIHNlbGVjdGlvbiBlbnRpcmVseTogdGhlIGNhbGxlciBpcyBhbm90aGVyIHN0b3JlIHdob3NlIGluZGV4IHNheXMgdGhpcyBNQUNISU5FIGhvbGRzIHRoZSBieXRlcyAtIHRoZSBwZXJzaXN0ZWQgaG9sZGVyIGlkZW50aXR5IGlzIGp1c3QgYSBVUkwsIHdoaWNoIGNhbm5vdCBuYW1lIGEgc3RvcmUuIFdoaWNoZXZlciBzdG9yZSdzIGZvbGRlciBoYXMgdGhlIG5ld2VzdCBjb3B5IGFuc3dlcnMuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZEJ1Y2tldEludGVybmFsKGFjY291bnQ6IHN0cmluZywgYnVja2V0TmFtZTogc3RyaW5nLCBjb25maWc6IHsgcGF0aDogc3RyaW5nOyByYW5nZT86IHsgc3RhcnQ6IG51bWJlcjsgZW5kOiBudW1iZXIgfTsgaW5jbHVkZVRvbWJzdG9uZXM/OiBib29sZWFuIH0pOiBQcm9taXNlPHsgZGF0YTogQnVmZmVyOyB3cml0ZVRpbWU6IG51bWJlcjsgc2l6ZTogbnVtYmVyIH0gfCB1bmRlZmluZWQ+IHtcbiAgICBsZXQgYnVja2V0ID0gYXdhaXQgcmVxdWlyZUJ1Y2tldChhY2NvdW50LCBidWNrZXROYW1lKTtcbiAgICBsZXQgcmVzdWx0cyA9IGF3YWl0IFByb21pc2UuYWxsKGJ1Y2tldC5zdG9yZXMubWFwKHMgPT4gcy5zdG9yZS5nZXQyKHsgcGF0aDogY29uZmlnLnBhdGgsIHJhbmdlOiBjb25maWcucmFuZ2UsIGluY2x1ZGVUb21ic3RvbmVzOiBjb25maWcuaW5jbHVkZVRvbWJzdG9uZXMsIGludGVybmFsOiB0cnVlIH0pKSk7XG4gICAgbGV0IGJlc3Q6IHsgZGF0YTogQnVmZmVyOyB3cml0ZVRpbWU6IG51bWJlcjsgc2l6ZTogbnVtYmVyIH0gfCB1bmRlZmluZWQ7XG4gICAgZm9yIChsZXQgcmVzdWx0IG9mIHJlc3VsdHMpIHtcbiAgICAgICAgaWYgKHJlc3VsdCAmJiAoIWJlc3QgfHwgcmVzdWx0LndyaXRlVGltZSA+IGJlc3Qud3JpdGVUaW1lKSkge1xuICAgICAgICAgICAgYmVzdCA9IHJlc3VsdDtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gYmVzdDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEJ1Y2tldENvbmZpZyhidWNrZXQ6IEJ1Y2tldFN0YXRlKTogQXJjaGl2ZXNDb25maWcge1xuICAgIGxldCBpbmRleCA9IHsgZmlsZUNvdW50OiAwLCBieXRlQ291bnQ6IDAgfTtcbiAgICBsZXQgaW5kZXhTb3VyY2VzOiB7IGRlYnVnTmFtZTogc3RyaW5nOyBmaWxlQ291bnQ6IG51bWJlcjsgYnl0ZUNvdW50OiBudW1iZXIgfVtdID0gW107XG4gICAgbGV0IHN5bmNpbmc6IFN5bmNBY3Rpdml0eVtdID0gW107XG4gICAgbGV0IHJlYWRlckRpc2tMaW1pdDogbnVtYmVyIHwgdW5kZWZpbmVkO1xuICAgIGZvciAobGV0IHMgb2YgYnVja2V0LnN0b3Jlcykge1xuICAgICAgICBsZXQgcHJvZ3Jlc3MgPSBzLnN0b3JlLmdldFN5bmNQcm9ncmVzcz8uKCk7XG4gICAgICAgIGlmICghcHJvZ3Jlc3MpIGNvbnRpbnVlO1xuICAgICAgICBpbmRleC5maWxlQ291bnQgKz0gcHJvZ3Jlc3MuaW5kZXguZmlsZUNvdW50O1xuICAgICAgICBpbmRleC5ieXRlQ291bnQgKz0gcHJvZ3Jlc3MuaW5kZXguYnl0ZUNvdW50O1xuICAgICAgICBpbmRleFNvdXJjZXMucHVzaCguLi5wcm9ncmVzcy5zb3VyY2VzKTtcbiAgICAgICAgc3luY2luZy5wdXNoKC4uLnByb2dyZXNzLnN5bmNpbmcpO1xuICAgICAgICByZWFkZXJEaXNrTGltaXQgPSByZWFkZXJEaXNrTGltaXQgfHwgcHJvZ3Jlc3MucmVhZGVyRGlza0xpbWl0O1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICAvLyBOYXRpdmUgY2hhbmdlLWZlZWQgc3VwcG9ydCA9IHRoZSBzdG9yZXMga2VlcCBhbiBpbmRleCAocmF3RGlzayBidWNrZXRzIGVtdWxhdGUgZ2V0Q2hhbmdlc0FmdGVyMiB3aXRoIGEgZnVsbCBsaXN0aW5nKSAtIGNsaWVudHMgdXNlIHRoaXMgdG8gcGljayB0aGVpciBzY2FuIGNhZGVuY2VcbiAgICAgICAgc3VwcG9ydHNDaGFuZ2VzQWZ0ZXI6IGJ1Y2tldC5zdG9yZXMuc29tZShzID0+IHMuc3RvcmUgaW5zdGFuY2VvZiBCbG9iU3RvcmUpLFxuICAgICAgICByZW1vdGVDb25maWc6IGJ1Y2tldC5yb3V0aW5nLFxuICAgICAgICBpbmRleCxcbiAgICAgICAgaW5kZXhTb3VyY2VzLFxuICAgICAgICByZWFkZXJEaXNrTGltaXQsXG4gICAgICAgIHN5bmNpbmcsXG4gICAgfTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGJ1Y2tldFN5bmNTdGF0dXMoYnVja2V0OiBCdWNrZXRTdGF0ZSk6IFByb21pc2U8QXJjaGl2ZXNTeW5jU3RhdHVzPiB7XG4gICAgbGV0IHN1cHBvcnRlZCA9IGJ1Y2tldC5zdG9yZXMuZmlsdGVyKHMgPT4gcy5zdG9yZS5nZXRTeW5jU3RhdHVzKTtcbiAgICBpZiAoIXN1cHBvcnRlZC5sZW5ndGgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBCdWNrZXQgJHtidWNrZXQuYWNjb3VudH0vJHtidWNrZXQuYnVja2V0TmFtZX0gZG9lcyBub3Qgc3VwcG9ydCBnZXRTeW5jU3RhdHVzIChyYXdEaXNrIGJ1Y2tldHMgaGF2ZSBubyBzeW5jaHJvbml6YXRpb24pYCk7XG4gICAgfVxuICAgIGxldCBzdGF0dXNlcyA9IGF3YWl0IFByb21pc2UuYWxsKHN1cHBvcnRlZC5tYXAoYXN5bmMgcyA9PiB7XG4gICAgICAgIGxldCBnZXRTeW5jU3RhdHVzID0gcy5zdG9yZS5nZXRTeW5jU3RhdHVzO1xuICAgICAgICBpZiAoIWdldFN5bmNTdGF0dXMpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgZ2V0U3luY1N0YXR1cyBkaXNhcHBlYXJlZCBmcm9tIGEgc3RvcmUgZm9yICR7YnVja2V0LmFjY291bnR9LyR7YnVja2V0LmJ1Y2tldE5hbWV9YCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGF3YWl0IGdldFN5bmNTdGF0dXMuY2FsbChzLnN0b3JlKTtcbiAgICB9KSk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgYWxsU2NhbnNDb21wbGV0ZTogc3RhdHVzZXMuZXZlcnkoeCA9PiB4LmFsbFNjYW5zQ29tcGxldGUpLFxuICAgICAgICBpbmRleFNpemU6IHN0YXR1c2VzLnJlZHVjZSgoc3VtLCB4KSA9PiBzdW0gKyB4LmluZGV4U2l6ZSwgMCksXG4gICAgICAgIHNvdXJjZXM6IHN0YXR1c2VzLmZsYXRNYXAoeCA9PiB4LnNvdXJjZXMpLFxuICAgIH07XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBidWNrZXRJbmRleFRvdGFscyhidWNrZXQ6IEJ1Y2tldFN0YXRlKTogUHJvbWlzZTx7IGZpbGVDb3VudDogbnVtYmVyOyBieXRlQ291bnQ6IG51bWJlcjsgc291cmNlczogeyBkZWJ1Z05hbWU6IHN0cmluZzsgZmlsZUNvdW50OiBudW1iZXI7IGJ5dGVDb3VudDogbnVtYmVyIH1bXSB9IHwgdW5kZWZpbmVkPiB7XG4gICAgbGV0IHN1cHBvcnRlZCA9IGJ1Y2tldC5zdG9yZXMuZmlsdGVyKHMgPT4gcy5zdG9yZS5jb21wdXRlSW5kZXhUb3RhbHMpO1xuICAgIGlmICghc3VwcG9ydGVkLmxlbmd0aCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBsZXQgdG90YWxzID0gYXdhaXQgUHJvbWlzZS5hbGwoc3VwcG9ydGVkLm1hcChhc3luYyBzID0+IHtcbiAgICAgICAgbGV0IGNvbXB1dGVJbmRleFRvdGFscyA9IHMuc3RvcmUuY29tcHV0ZUluZGV4VG90YWxzO1xuICAgICAgICBpZiAoIWNvbXB1dGVJbmRleFRvdGFscykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBjb21wdXRlSW5kZXhUb3RhbHMgZGlzYXBwZWFyZWQgZnJvbSBhIHN0b3JlIGZvciAke2J1Y2tldC5hY2NvdW50fS8ke2J1Y2tldC5idWNrZXROYW1lfWApO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhd2FpdCBjb21wdXRlSW5kZXhUb3RhbHMuY2FsbChzLnN0b3JlKTtcbiAgICB9KSk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZmlsZUNvdW50OiB0b3RhbHMucmVkdWNlKChzdW0sIHgpID0+IHN1bSArIHguZmlsZUNvdW50LCAwKSxcbiAgICAgICAgYnl0ZUNvdW50OiB0b3RhbHMucmVkdWNlKChzdW0sIHgpID0+IHN1bSArIHguYnl0ZUNvdW50LCAwKSxcbiAgICAgICAgc291cmNlczogdG90YWxzLmZsYXRNYXAoeCA9PiB4LnNvdXJjZXMpLFxuICAgIH07XG59XG5cbmNvbnN0IGJ1Y2tldHMgPSBuZXcgTWFwPHN0cmluZywgUHJvbWlzZTxCdWNrZXRTdGF0ZSB8IHVuZGVmaW5lZD4+KCk7XG5cbmNvbnN0IE1BWF9SRUJVSUxEX1RJTUVSX0RFTEFZID0gMiAqKiAzMSAtIDE7XG5jb25zdCBSRUJVSUxEX0JPVU5EQVJZX0JVRkZFUiA9IDEwMDA7XG5cbmZ1bmN0aW9uIHNjaGVkdWxlV2luZG93Qm91bmRhcnlSZWJ1aWxkKGxvYWRlZDogQnVja2V0U3RhdGUpOiB2b2lkIHtcbiAgICBsZXQgbm93ID0gRGF0ZS5ub3coKTtcbiAgICBsZXQgYm91bmRhcmllcyA9IGxvYWRlZC5zZWxmRW50cmllcy5mbGF0TWFwKHggPT4geC52YWxpZFdpbmRvdykuZmlsdGVyKHQgPT4gdCA+IG5vdyk7XG4gICAgaWYgKCFib3VuZGFyaWVzLmxlbmd0aCkgcmV0dXJuO1xuICAgIGxldCBuZXh0Qm91bmRhcnkgPSBNYXRoLm1pbiguLi5ib3VuZGFyaWVzKTtcbiAgICBsZXQga2V5ID0gYCR7bG9hZGVkLmFjY291bnR9LyR7bG9hZGVkLmJ1Y2tldE5hbWV9YDtcbiAgICBsZXQgdGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgdm9pZCAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgICAgbGV0IGN1cnJlbnQgPSBhd2FpdCBidWNrZXRzLmdldChrZXkpO1xuICAgICAgICAgICAgaWYgKGN1cnJlbnQgIT09IGxvYWRlZCkgcmV0dXJuO1xuICAgICAgICAgICAgaWYgKERhdGUubm93KCkgPCBuZXh0Qm91bmRhcnkpIHtcbiAgICAgICAgICAgICAgICBzY2hlZHVsZVdpbmRvd0JvdW5kYXJ5UmVidWlsZChsb2FkZWQpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGF3YWl0IHNjaGVkdWxlUm91dGluZ1JlbG9hZChsb2FkZWQuYWNjb3VudCwgbG9hZGVkLmJ1Y2tldE5hbWUsIHsgZm9yY2U6IHRydWUsIHJlYXNvbjogXCJhIHZhbGlkIHdpbmRvdyBib3VuZGFyeSBwYXNzZWRcIiB9KTtcbiAgICAgICAgfSkoKTtcbiAgICB9LCBNYXRoLm1pbihuZXh0Qm91bmRhcnkgLSBub3cgKyBSRUJVSUxEX0JPVU5EQVJZX0JVRkZFUiwgTUFYX1JFQlVJTERfVElNRVJfREVMQVkpKTtcbiAgICAodGltZXIgYXMgeyB1bnJlZj86ICgpID0+IHZvaWQgfSkudW5yZWY/LigpO1xufVxuXG5jb25zdCBCT1VOREFSWV9TQ0FOX09GRlNFVFMgPSBbLTMwICogMTAwMCwgMiAqIDEwMDAsIDMwICogMTAwMF07XG5jb25zdCBCT1VOREFSWV9TQ0FOX0xPT0tCQUNLID0gREVGQVVMVF9GQVNUX1dSSVRFX0RFTEFZICsgV0lORE9XX0VORF9GTFVTSF9NQVJHSU47XG5jb25zdCBTVEFSVFVQX0JPVU5EQVJZX1NDQU5fREVMQVkgPSAzMCAqIDEwMDA7XG5cbmNvbnN0IHNjaGVkdWxlZEJvdW5kYXJ5U2NhbnMgPSBuZXcgU2V0PHN0cmluZz4oKTtcbmNvbnN0IGJvdW5kYXJ5U2NhbnNSdW5uaW5nID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbmZ1bmN0aW9uIHNjaGVkdWxlQm91bmRhcnlTY2Fucyhsb2FkZWQ6IEJ1Y2tldFN0YXRlKTogdm9pZCB7XG4gICAgbGV0IGtleSA9IGAke2xvYWRlZC5hY2NvdW50fS8ke2xvYWRlZC5idWNrZXROYW1lfWA7XG4gICAgbGV0IG5vdyA9IERhdGUubm93KCk7XG4gICAgbGV0IHN0YXJ0cyA9IG5ldyBTZXQ8bnVtYmVyPigpO1xuICAgIGZvciAobGV0IHNlbGYgb2YgbG9hZGVkLnNlbGZFbnRyaWVzKSB7XG4gICAgICAgIGxldCBzdGFydCA9IHNlbGYudmFsaWRXaW5kb3dbMF07XG4gICAgICAgIGlmIChzdGFydCA+IG5vdyAmJiBzdGFydCA8IE51bWJlci5NQVhfU0FGRV9JTlRFR0VSKSB7XG4gICAgICAgICAgICBzdGFydHMuYWRkKHN0YXJ0KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBmb3IgKGxldCBzZWxmIG9mIGxvYWRlZC5zZWxmRW50cmllcykge1xuICAgICAgICBsZXQgW3N0YXJ0LCBlbmRdID0gc2VsZi52YWxpZFdpbmRvdztcbiAgICAgICAgaWYgKCEoc3RhcnQgPD0gbm93ICYmIG5vdyA8IGVuZCkgfHwgc3RhcnQgPD0gMCkgY29udGludWU7XG4gICAgICAgIGlmIChub3cgLSBzdGFydCA+IEJPVU5EQVJZX1NDQU5fTE9PS0JBQ0spIGNvbnRpbnVlO1xuICAgICAgICBsZXQgc2NoZWR1bGVLZXkgPSBgJHtrZXl9fCR7c3RhcnR9fHN0YXJ0dXBgO1xuICAgICAgICBpZiAoc2NoZWR1bGVkQm91bmRhcnlTY2Fucy5oYXMoc2NoZWR1bGVLZXkpKSBjb250aW51ZTtcbiAgICAgICAgc2NoZWR1bGVkQm91bmRhcnlTY2Fucy5hZGQoc2NoZWR1bGVLZXkpO1xuICAgICAgICBsZXQgdGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIHZvaWQgcnVuQm91bmRhcnlTY2FuKGtleSwgc3RhcnQsIFNUQVJUVVBfQk9VTkRBUllfU0NBTl9ERUxBWSwgXCJzdGFydHVwKzMwc1wiKS5jYXRjaCgoZTogRXJyb3IpID0+IGNvbnNvbGUuZXJyb3IoYEJvdW5kYXJ5IHNjYW4gZm9yIGJ1Y2tldCAke2tleX0gZmFpbGVkOiAke2Uuc3RhY2sgPz8gZX1gKSk7XG4gICAgICAgIH0sIFNUQVJUVVBfQk9VTkRBUllfU0NBTl9ERUxBWSk7XG4gICAgICAgICh0aW1lciBhcyB7IHVucmVmPzogKCkgPT4gdm9pZCB9KS51bnJlZj8uKCk7XG4gICAgfVxuICAgIGZvciAobGV0IHN0YXJ0IG9mIHN0YXJ0cykge1xuICAgICAgICBmb3IgKGxldCBvZmZzZXQgb2YgQk9VTkRBUllfU0NBTl9PRkZTRVRTKSB7XG4gICAgICAgICAgICBsZXQgYXQgPSBzdGFydCArIG9mZnNldDtcbiAgICAgICAgICAgIGlmIChhdCA8PSBub3cpIGNvbnRpbnVlO1xuICAgICAgICAgICAgbGV0IHNjaGVkdWxlS2V5ID0gYCR7a2V5fXwke3N0YXJ0fXwke29mZnNldH1gO1xuICAgICAgICAgICAgaWYgKHNjaGVkdWxlZEJvdW5kYXJ5U2NhbnMuaGFzKHNjaGVkdWxlS2V5KSkgY29udGludWU7XG4gICAgICAgICAgICBzY2hlZHVsZWRCb3VuZGFyeVNjYW5zLmFkZChzY2hlZHVsZUtleSk7XG4gICAgICAgICAgICBsZXQgYXJtID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGxldCB0aW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoRGF0ZS5ub3coKSA8IGF0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcm0oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2b2lkIHJ1bkJvdW5kYXJ5U2NhbihrZXksIHN0YXJ0LCBvZmZzZXQpLmNhdGNoKChlOiBFcnJvcikgPT4gY29uc29sZS5lcnJvcihgQm91bmRhcnkgc2NhbiBmb3IgYnVja2V0ICR7a2V5fSBmYWlsZWQ6ICR7ZS5zdGFjayA/PyBlfWApKTtcbiAgICAgICAgICAgICAgICB9LCBNYXRoLm1pbihhdCAtIERhdGUubm93KCksIE1BWF9SRUJVSUxEX1RJTUVSX0RFTEFZKSk7XG4gICAgICAgICAgICAgICAgKHRpbWVyIGFzIHsgdW5yZWY/OiAoKSA9PiB2b2lkIH0pLnVucmVmPy4oKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBhcm0oKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gcnVuQm91bmRhcnlTY2FuKGJ1Y2tldEtleTogc3RyaW5nLCB3aW5kb3dTdGFydDogbnVtYmVyLCBvZmZzZXQ6IG51bWJlciwgb2Zmc2V0TGFiZWw/OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsZXQgbGFiZWwgPSBgYnVja2V0ICR7YnVja2V0S2V5fSwgd2luZG93IHN0YXJ0aW5nICR7bmV3IERhdGUod2luZG93U3RhcnQpLnRvSVNPU3RyaW5nKCl9LCBvZmZzZXQgJHtvZmZzZXRMYWJlbCB8fCBgJHtvZmZzZXQgLyAxMDAwfXNgfWA7XG4gICAgaWYgKGJvdW5kYXJ5U2NhbnNSdW5uaW5nLmhhcyhidWNrZXRLZXkpKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBTa2lwcGluZyBib3VuZGFyeSBzY2FuICgke2xhYmVsfSk6IHRoZSBwcmV2aW91cyBib3VuZGFyeSBzY2FuIGlzIHN0aWxsIHJ1bm5pbmdgKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBib3VuZGFyeVNjYW5zUnVubmluZy5hZGQoYnVja2V0S2V5KTtcbiAgICB0cnkge1xuICAgICAgICBsZXQgbG9hZGVkID0gYXdhaXQgYnVja2V0cy5nZXQoYnVja2V0S2V5KTtcbiAgICAgICAgaWYgKCFsb2FkZWQpIHJldHVybjtcbiAgICAgICAgbGV0IGVmZmVjdGl2ZSA9IGxvYWRlZC5yb3V0aW5nO1xuICAgICAgICBsZXQgc2VsZkluZGV4ZXMgPSBmaW5kU2VsZkluZGV4ZXMoZWZmZWN0aXZlLCBsb2FkZWQuYWNjb3VudCwgbG9hZGVkLmJ1Y2tldE5hbWUpO1xuICAgICAgICBsZXQgc2VsZkluZGV4U2V0ID0gbmV3IFNldChzZWxmSW5kZXhlcyk7XG4gICAgICAgIGxldCBzZWx2ZXMgPSBzZWxmSW5kZXhlcy5tYXAoaSA9PiBlZmZlY3RpdmUuc291cmNlc1tpXSBhcyBIb3N0ZWRDb25maWcpLmZpbHRlcih4ID0+IHgudmFsaWRXaW5kb3dbMF0gPT09IHdpbmRvd1N0YXJ0KTtcbiAgICAgICAgaWYgKCFzZWx2ZXMubGVuZ3RoKSByZXR1cm47XG4gICAgICAgIGxldCBwcmV2VGltZSA9IHdpbmRvd1N0YXJ0IC0gMTtcbiAgICAgICAgLy8gRXZlcnl0aGluZyBpcyBwZXItc3RvcmU6IGVhY2ggc2VsZiBlbnRyeSdzIHJvdXRlIGhhcyBpdHMgb3duIHN0b3JlLCBhbmQgdGhhdCBzdG9yZSdzIGRpc2svcmVtb3RlIGJvdW5kYXJ5IHB1bGxzIG9ubHkgY29uY2VybiBpdHMgb3duIHJvdXRlIHNsaWNlXG4gICAgICAgIGxldCBuZWVkRGlza1NjYW4gPSBuZXcgU2V0PExvYWRlZFN0b3JlPigpO1xuICAgICAgICBsZXQgcmVtb3RlT3duZXJzID0gbmV3IE1hcDxMb2FkZWRTdG9yZSwgTWFwPG51bWJlciwgW251bWJlciwgbnVtYmVyXT4+KCk7XG4gICAgICAgIGZvciAobGV0IHNlbGYgb2Ygc2VsdmVzKSB7XG4gICAgICAgICAgICBsZXQgc2VsZlJvdXRlID0gc2VsZi5yb3V0ZSB8fCBGVUxMX1JPVVRFO1xuICAgICAgICAgICAgbGV0IHNlbGZTdG9yZSA9IGxvYWRlZC5zdG9yZXMuZmluZCh4ID0+IHgucm91dGVLZXkgPT09IEpTT04uc3RyaW5naWZ5KHNlbGZSb3V0ZSkpO1xuICAgICAgICAgICAgaWYgKCFzZWxmU3RvcmUgfHwgIShzZWxmU3RvcmUuc3RvcmUgaW5zdGFuY2VvZiBCbG9iU3RvcmUpKSBjb250aW51ZTtcbiAgICAgICAgICAgIGxldCBpZHggPSBlZmZlY3RpdmUuc291cmNlcy5pbmRleE9mKHNlbGYpO1xuICAgICAgICAgICAgbGV0IHNoYWRvd2VkID0gZmFsc2U7XG4gICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGlkeDsgaisrKSB7XG4gICAgICAgICAgICAgICAgbGV0IG90aGVyID0gZWZmZWN0aXZlLnNvdXJjZXNbal07XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvdGhlciA9PT0gXCJzdHJpbmdcIikgY29udGludWU7XG4gICAgICAgICAgICAgICAgbGV0IFt3cywgd2VdID0gb3RoZXIudmFsaWRXaW5kb3c7XG4gICAgICAgICAgICAgICAgaWYgKCEod3MgPD0gd2luZG93U3RhcnQgJiYgd2luZG93U3RhcnQgPCB3ZSkpIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGxldCByID0gb3RoZXIucm91dGUgfHwgRlVMTF9ST1VURTtcbiAgICAgICAgICAgICAgICBpZiAoclswXSA8PSBzZWxmUm91dGVbMF0gJiYgc2VsZlJvdXRlWzFdIDw9IHJbMV0pIHtcbiAgICAgICAgICAgICAgICAgICAgc2hhZG93ZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2hhZG93ZWQpIGNvbnRpbnVlO1xuICAgICAgICAgICAgbGV0IHVuY292ZXJlZDogW251bWJlciwgbnVtYmVyXVtdID0gW1tzZWxmUm91dGVbMF0sIHNlbGZSb3V0ZVsxXV1dO1xuICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBlZmZlY3RpdmUuc291cmNlcy5sZW5ndGggJiYgdW5jb3ZlcmVkLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgbGV0IG90aGVyID0gZWZmZWN0aXZlLnNvdXJjZXNbal07XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvdGhlciA9PT0gXCJzdHJpbmdcIikgY29udGludWU7XG4gICAgICAgICAgICAgICAgbGV0IFt3cywgd2VdID0gb3RoZXIudmFsaWRXaW5kb3c7XG4gICAgICAgICAgICAgICAgaWYgKCEod3MgPD0gcHJldlRpbWUgJiYgcHJldlRpbWUgPCB3ZSkpIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGxldCByID0gb3RoZXIucm91dGUgfHwgRlVMTF9ST1VURTtcbiAgICAgICAgICAgICAgICBsZXQgcmVtYWluaW5nOiBbbnVtYmVyLCBudW1iZXJdW10gPSBbXTtcbiAgICAgICAgICAgICAgICBsZXQgY2xhaW1lZDogW251bWJlciwgbnVtYmVyXSB8IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICBmb3IgKGxldCB1IG9mIHVuY292ZXJlZCkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgaW50ZXIgPSByb3V0ZUludGVyc2VjdGlvbih1LCByKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpbnRlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtYWluaW5nLnB1c2godSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjbGFpbWVkID0gY2xhaW1lZCAmJiBbTWF0aC5taW4oY2xhaW1lZFswXSwgaW50ZXJbMF0pLCBNYXRoLm1heChjbGFpbWVkWzFdLCBpbnRlclsxXSldIGFzIFtudW1iZXIsIG51bWJlcl0gfHwgaW50ZXI7XG4gICAgICAgICAgICAgICAgICAgIGlmICh1WzBdIDwgaW50ZXJbMF0pIHJlbWFpbmluZy5wdXNoKFt1WzBdLCBpbnRlclswXV0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW50ZXJbMV0gPCB1WzFdKSByZW1haW5pbmcucHVzaChbaW50ZXJbMV0sIHVbMV1dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdW5jb3ZlcmVkID0gcmVtYWluaW5nO1xuICAgICAgICAgICAgICAgIGlmICghY2xhaW1lZCkgY29udGludWU7XG4gICAgICAgICAgICAgICAgaWYgKHNlbGZJbmRleFNldC5oYXMoaikpIHtcbiAgICAgICAgICAgICAgICAgICAgbmVlZERpc2tTY2FuLmFkZChzZWxmU3RvcmUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBvd25lcnMgPSByZW1vdGVPd25lcnMuZ2V0KHNlbGZTdG9yZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICghb3duZXJzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvd25lcnMgPSBuZXcgTWFwKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdGVPd25lcnMuc2V0KHNlbGZTdG9yZSwgb3duZXJzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBsZXQgZXhpc3RpbmcgPSBvd25lcnMuZ2V0KGopO1xuICAgICAgICAgICAgICAgICAgICBvd25lcnMuc2V0KGosIGV4aXN0aW5nICYmIFtNYXRoLm1pbihleGlzdGluZ1swXSwgY2xhaW1lZFswXSksIE1hdGgubWF4KGV4aXN0aW5nWzFdLCBjbGFpbWVkWzFdKV0gYXMgW251bWJlciwgbnVtYmVyXSB8fCBjbGFpbWVkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFuZWVkRGlza1NjYW4uc2l6ZSAmJiAhcmVtb3RlT3duZXJzLnNpemUpIHJldHVybjtcbiAgICAgICAgY29uc29sZS5sb2coYEJvdW5kYXJ5IHNjYW4gKCR7bGFiZWx9KTogZGlza1NjYW5zPSR7bmVlZERpc2tTY2FuLnNpemV9LCBzdG9yZXMgd2l0aCByZW1vdGUgcHJldmlvdXMtd2luZG93IG93bmVyczogJHtyZW1vdGVPd25lcnMuc2l6ZX1gKTtcbiAgICAgICAgZm9yIChsZXQgc2VsZlN0b3JlIG9mIG5lZWREaXNrU2Nhbikge1xuICAgICAgICAgICAgaWYgKHNlbGZTdG9yZS5zdG9yZSBpbnN0YW5jZW9mIEJsb2JTdG9yZSkge1xuICAgICAgICAgICAgICAgIGF3YWl0IHNlbGZTdG9yZS5zdG9yZS5yZXNjYW5CYXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHNpbmNlID0gd2luZG93U3RhcnQgLSBCT1VOREFSWV9TQ0FOX0xPT0tCQUNLO1xuICAgICAgICBmb3IgKGxldCBbc2VsZlN0b3JlLCBvd25lcnNdIG9mIHJlbW90ZU93bmVycykge1xuICAgICAgICAgICAgaWYgKCEoc2VsZlN0b3JlLnN0b3JlIGluc3RhbmNlb2YgQmxvYlN0b3JlKSkgY29udGludWU7XG4gICAgICAgICAgICBmb3IgKGxldCBbc291cmNlSW5kZXgsIHJvdXRlXSBvZiBvd25lcnMpIHtcbiAgICAgICAgICAgICAgICBsZXQgb3duZXJTb3VyY2UgPSBlZmZlY3RpdmUuc291cmNlc1tzb3VyY2VJbmRleF07XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvd25lclNvdXJjZSA9PT0gXCJzdHJpbmdcIikgY29udGludWU7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgc2VsZlN0b3JlLnN0b3JlLmJvdW5kYXJ5U2NhblJlbW90ZShjcmVhdGVBcGlBcmNoaXZlcyhvd25lclNvdXJjZSksIHsgc2luY2UsIHJvdXRlIH0pO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcihgQm91bmRhcnkgc2NhbiAoJHtsYWJlbH0pIG9mIHByZXZpb3VzLXdpbmRvdyBvd25lciAoc291cmNlIGluZGV4ICR7c291cmNlSW5kZXh9KSBmYWlsZWQ6ICR7KGUgYXMgRXJyb3IpLnN0YWNrID8/IGV9YCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgYm91bmRhcnlTY2Fuc1J1bm5pbmcuZGVsZXRlKGJ1Y2tldEtleSk7XG4gICAgfVxufVxuXG5jb25zdCByZXNvbHZlZFNvdXJjZUFyY2hpdmVzID0gbmV3IE1hcDxzdHJpbmcsIElBcmNoaXZlcz4oKTtcbi8qKiBBIGNhY2hlZCBJQXJjaGl2ZXMgZm9yIGEgcGVyc2lzdGVkIHNvdXJjZSBpZGVudGl0eTogYSByb3V0aW5nIFVSTCAoaG9zdGVkL2JhY2tibGF6ZSkgb3IgYSBkaXNrIGZvbGRlciBwYXRoIC0gdGhlIGZvcm0gQmxvYlN0b3JlJ3Mgc291cmNlcyBsaXN0IHN0b3Jlcy4gQ29uZmlndXJhdGlvbiAodmFsaWQgd2luZG93cywgcm91dGVzKSBkZWNpZGVzIFdIRU4gYSBzb3VyY2Ugc2hvdWxkIGJlIHVzZWQ7IGZvciByZWFkaW5nIGJ5dGVzIHRoZSBpbmRleCBzYXlzIGEgc291cmNlIGhvbGRzLCB0aGUgVVJMIGFsb25lIGlzIGVub3VnaCAtIGV2ZW4gZm9yIHNvdXJjZXMgbm8gbG9uZ2VyIGluIGFueSBjb25maWcuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZVNvdXJjZUFyY2hpdmVzKHVybDogc3RyaW5nKTogSUFyY2hpdmVzIHtcbiAgICBsZXQgZXhpc3RpbmcgPSByZXNvbHZlZFNvdXJjZUFyY2hpdmVzLmdldCh1cmwpO1xuICAgIGlmIChleGlzdGluZykgcmV0dXJuIGV4aXN0aW5nO1xuICAgIGxldCBhcmNoaXZlczogSUFyY2hpdmVzO1xuICAgIGlmICh1cmwuc3RhcnRzV2l0aChcImh0dHBzOi8vXCIpKSB7XG4gICAgICAgIC8vIFRoZSBjb25maWcgaXMgZmFicmljYXRlZCBmcm9tIHRoZSBiYXJlIFVSTCBhbmQgY2FuIG5ldmVyIGV4YWN0LW1hdGNoIGEgc2VydmVyJ3MgZW50cmllcyAtIHdoaWNoIGlzIGZpbmUsIGJlY2F1c2UgaG9sZGVyIHJlYWRzIGFyZSBpbnRlcm5hbCByZWFkcywgYW5kIGludGVybmFsIHJlYWRzIG5ldmVyIHNlbGVjdCBhIHN0b3JlIChzZWUgcmVhZEJ1Y2tldEludGVybmFsKVxuICAgICAgICBhcmNoaXZlcyA9IGNyZWF0ZUFwaUFyY2hpdmVzKG5vcm1hbGl6ZVNvdXJjZSh1cmwpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBhcmNoaXZlcyA9IG5ldyBBcmNoaXZlc0Rpc2sodXJsKTtcbiAgICB9XG4gICAgcmVzb2x2ZWRTb3VyY2VBcmNoaXZlcy5zZXQodXJsLCBhcmNoaXZlcyk7XG4gICAgcmV0dXJuIGFyY2hpdmVzO1xufVxuXG5mdW5jdGlvbiBzb3VyY2VJZGVudGl0eShzb3VyY2VDb25maWc6IFNvdXJjZUNvbmZpZyB8IHVuZGVmaW5lZCk6IHN0cmluZyB7XG4gICAgaWYgKCFzb3VyY2VDb25maWcpIHJldHVybiBcImRpc2tcIjtcbiAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoeyAuLi5zb3VyY2VDb25maWcsIHZhbGlkV2luZG93OiB1bmRlZmluZWQsIHJvdXRlOiB1bmRlZmluZWQgfSk7XG59XG5cbmZ1bmN0aW9uIGJ1aWxkU3RvcmUoYWNjb3VudDogc3RyaW5nLCBidWNrZXROYW1lOiBzdHJpbmcsIHBsYW5TdG9yZTogU3RvcmVQbGFuU3RvcmUpOiBJQnVja2V0U3RvcmUge1xuICAgIGxldCBmb2xkZXIgPSBnZXRCdWNrZXRGb2xkZXIoYWNjb3VudCwgYnVja2V0TmFtZSwgcGxhblN0b3JlLnJvdXRlKTtcbiAgICBpZiAocGxhblN0b3JlLnJhd0Rpc2spIHtcbiAgICAgICAgcmV0dXJuIG5ldyBSYXdEaXNrU3RvcmUobmV3IEFyY2hpdmVzRGlzayhmb2xkZXIpKTtcbiAgICB9XG4gICAgbGV0IHNvdXJjZXM6IEFyY2hpdmVzU291cmNlW10gPSBwbGFuU3RvcmUuc291cmNlU3BlY3MubWFwKHNwZWMgPT4gKHtcbiAgICAgICAgc291cmNlOiBzcGVjLnNvdXJjZUNvbmZpZyAmJiBjcmVhdGVBcGlBcmNoaXZlcyhzcGVjLnNvdXJjZUNvbmZpZykgfHwgbmV3IEFyY2hpdmVzRGlzayhmb2xkZXIpLFxuICAgICAgICB1cmw6IHNwZWMuc291cmNlQ29uZmlnPy51cmwgfHwgZm9sZGVyLFxuICAgICAgICB2YWxpZFdpbmRvd3M6IHNwZWMudmFsaWRXaW5kb3dzLFxuICAgICAgICByb3V0ZTogc3BlYy5yb3V0ZSxcbiAgICAgICAgbm9GdWxsU3luYzogc3BlYy5ub0Z1bGxTeW5jLFxuICAgICAgICBpbnRlcm1lZGlhdGU6IHNwZWMuc291cmNlQ29uZmlnPy5pbnRlcm1lZGlhdGUsXG4gICAgICAgIHNvdXJjZUNvbmZpZzogc3BlYy5zb3VyY2VDb25maWcsXG4gICAgICAgIGlkZW50aXR5OiBzb3VyY2VJZGVudGl0eShzcGVjLnNvdXJjZUNvbmZpZyksXG4gICAgfSkpO1xuICAgIHJldHVybiBuZXcgQmxvYlN0b3JlKGZvbGRlciwgc291cmNlcywge1xuICAgICAgICByZWFkZXJEaXNrTGltaXQ6IHBsYW5TdG9yZS5yZWFkZXJEaXNrTGltaXQsXG4gICAgICAgIG9uV3JpdGVDb3VudGVkOiAoa2luZCwgYnl0ZXMpID0+IGNvdW50QnVja2V0V3JpdGUoYCR7YWNjb3VudH0vJHtidWNrZXROYW1lfWAsIGtpbmQsIGJ5dGVzKSxcbiAgICAgICAgcmVzb2x2ZVNvdXJjZVVybDogcmVzb2x2ZVNvdXJjZUFyY2hpdmVzLFxuICAgICAgICBlbnRyaWVzOiBwbGFuU3RvcmUuZW50cmllcyxcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gYnVpbGRCdWNrZXQoYWNjb3VudDogc3RyaW5nLCBidWNrZXROYW1lOiBzdHJpbmcsIHJvdXRpbmc6IFJlbW90ZUNvbmZpZywgcGxhbj86IFN0b3JlUGxhbik6IEJ1Y2tldFN0YXRlIHtcbiAgICBpZiAoIXBsYW4pIHtcbiAgICAgICAgcGxhbiA9IGNvbXB1dGVTdG9yZVBsYW4oYWNjb3VudCwgYnVja2V0TmFtZSwgcm91dGluZyk7XG4gICAgfVxuICAgIGxldCB7IHNlbGZFbnRyaWVzLCBzZWxmIH0gPSBwbGFuO1xuICAgIGlmICghc2VsZikge1xuICAgICAgICBjb25zb2xlLmxvZyhgVGhpcyBzZXJ2ZXIgaXMgbm90IGluIHRoZSByb3V0aW5nIGNvbmZpZyBmb3IgYnVja2V0ICR7YWNjb3VudH0vJHtidWNrZXROYW1lfTogbm8gbG9uZ2VyIHN5bmNocm9uaXppbmcsIHZhbGlkIHdpbmRvdyB0cmVhdGVkIGFzIFswLCAwXSAoZmFzdCB3cml0ZXMgZmx1c2ggaW1tZWRpYXRlbHkpLCBkaXNrIGRhdGEga2VwdCBhbmQgc2VydmVkYCk7XG4gICAgfVxuICAgIGxldCBzdG9yZXM6IExvYWRlZFN0b3JlW10gPSBwbGFuLnN0b3Jlcy5tYXAocGxhblN0b3JlID0+ICh7XG4gICAgICAgIHJvdXRlS2V5OiBwbGFuU3RvcmUucm91dGVLZXksXG4gICAgICAgIHJvdXRlOiBwbGFuU3RvcmUucm91dGUsXG4gICAgICAgIGVudHJpZXM6IHBsYW5TdG9yZS5lbnRyaWVzLFxuICAgICAgICBmb2xkZXI6IGdldEJ1Y2tldEZvbGRlcihhY2NvdW50LCBidWNrZXROYW1lLCBwbGFuU3RvcmUucm91dGUpLFxuICAgICAgICBzdG9yZTogYnVpbGRTdG9yZShhY2NvdW50LCBidWNrZXROYW1lLCBwbGFuU3RvcmUpLFxuICAgIH0pKTtcbiAgICBsZXQgbG9hZGVkOiBCdWNrZXRTdGF0ZSA9IHsgYWNjb3VudCwgYnVja2V0TmFtZSwgcm91dGluZywgcm91dGluZ0pTT046IEpTT04uc3RyaW5naWZ5KHJvdXRpbmcpLCBzZWxmRW50cmllcywgc2VsZiwgc3RvcmVzLCBzdHJ1Y3R1cmVLZXk6IHBsYW4uc3RydWN0dXJlS2V5IH07XG4gICAgc2NoZWR1bGVXaW5kb3dCb3VuZGFyeVJlYnVpbGQobG9hZGVkKTtcbiAgICBzY2hlZHVsZUJvdW5kYXJ5U2NhbnMobG9hZGVkKTtcbiAgICAvLyBBIGxvYWRlZCBidWNrZXQgbXVzdCBhY3R1YWxseSBiZSBydW5uaW5nOiBlYWNoIHN0b3JlJ3MgaW5pdCBsb2FkcyBpdHMgaW5kZXggYW5kIHN0YXJ0cyBpdHMgc291cmNlIHN5bmNocm9uaXphdGlvbiwgYW5kIGl0IGlzIGxhenksIHNvIHdpdGhvdXQgdGhpcyBhIGJ1Y2tldCBub3RoaW5nIGhhcyByZWFkIGZyb20gb3Igd3JpdHRlbiB0byBzaXRzIGluZXJ0IC0gcmVwb3J0aW5nIG5vIGRhdGEgYW5kIG5vIHN5bmNpbmcgd2hpbGUgaXRzIGRpc2sgaXMgZnVsbCBvZiBmaWxlcy5cbiAgICBmb3IgKGxldCBzIG9mIHN0b3Jlcykge1xuICAgICAgICBpZiAocy5zdG9yZSBpbnN0YW5jZW9mIEJsb2JTdG9yZSkge1xuICAgICAgICAgICAgbGV0IHN0b3JlID0gcy5zdG9yZTtcbiAgICAgICAgICAgIHZvaWQgc3RvcmUuaW5pdCgpLmNhdGNoKChlOiBFcnJvcikgPT4gY29uc29sZS5lcnJvcihgSW5pdGlhbGl6aW5nIHRoZSBzdG9yZSBmb3IgYnVja2V0ICR7YWNjb3VudH0vJHtidWNrZXROYW1lfSAocm91dGUgJHtzLnJvdXRlS2V5fSkgZmFpbGVkOiAke2Uuc3RhY2sgPz8gZX1gKSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGxvYWRlZDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gbG9hZEJ1Y2tldChhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZyk6IFByb21pc2U8QnVja2V0U3RhdGUgfCB1bmRlZmluZWQ+IHtcbiAgICBsZXQgcm91dGluZyA9IGF3YWl0IHJlYWRSb3V0aW5nRnJvbURpc2soYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgaWYgKCFyb3V0aW5nKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHJldHVybiBidWlsZEJ1Y2tldChhY2NvdW50LCBidWNrZXROYW1lLCByb3V0aW5nKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldExvYWRlZEJ1Y2tldChhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZyk6IFByb21pc2U8QnVja2V0U3RhdGUgfCB1bmRlZmluZWQ+IHtcbiAgICBsZXQga2V5ID0gYCR7YWNjb3VudH0vJHtidWNrZXROYW1lfWA7XG4gICAgbGV0IGxvYWRlZCA9IGJ1Y2tldHMuZ2V0KGtleSk7XG4gICAgaWYgKCFsb2FkZWQpIHtcbiAgICAgICAgbG9hZGVkID0gbG9hZEJ1Y2tldChhY2NvdW50LCBidWNrZXROYW1lKTtcbiAgICAgICAgYnVja2V0cy5zZXQoa2V5LCBsb2FkZWQpO1xuICAgICAgICB2b2lkIGxvYWRlZC50aGVuKGJ1Y2tldCA9PiB7XG4gICAgICAgICAgICBpZiAoIWJ1Y2tldCAmJiBidWNrZXRzLmdldChrZXkpID09PSBsb2FkZWQpIHtcbiAgICAgICAgICAgICAgICBidWNrZXRzLmRlbGV0ZShrZXkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCAoKSA9PiB7XG4gICAgICAgICAgICBpZiAoYnVja2V0cy5nZXQoa2V5KSA9PT0gbG9hZGVkKSB7XG4gICAgICAgICAgICAgICAgYnVja2V0cy5kZWxldGUoa2V5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBsb2FkZWQ7XG59XG5cbmNvbnN0IHJvdXRpbmdSZWxvYWRzID0gbmV3IE1hcDxzdHJpbmcsIFByb21pc2U8dm9pZD4+KCk7XG5mdW5jdGlvbiBzY2hlZHVsZVJvdXRpbmdSZWxvYWQoYWNjb3VudDogc3RyaW5nLCBidWNrZXROYW1lOiBzdHJpbmcsIGNvbmZpZz86IHsgZm9yY2U/OiBib29sZWFuOyByZWFzb24/OiBzdHJpbmcgfSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGxldCBrZXkgPSBgJHthY2NvdW50fS8ke2J1Y2tldE5hbWV9YDtcbiAgICBsZXQgbmV4dCA9IChyb3V0aW5nUmVsb2Fkcy5nZXQoa2V5KSB8fCBQcm9taXNlLnJlc29sdmUoKSlcbiAgICAgICAgLnRoZW4oKCkgPT4gY2hlY2tSb3V0aW5nQ2hhbmdlZChhY2NvdW50LCBidWNrZXROYW1lLCBjb25maWcpKVxuICAgICAgICAuY2F0Y2goZSA9PiBjb25zb2xlLmVycm9yKGBSZWxvYWRpbmcgcm91dGluZyBjb25maWcgZm9yIGJ1Y2tldCAke2tleX0gZmFpbGVkOmAsIGUpKTtcbiAgICByb3V0aW5nUmVsb2Fkcy5zZXQoa2V5LCBuZXh0KTtcbiAgICByZXR1cm4gbmV4dDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gY2hlY2tSb3V0aW5nQ2hhbmdlZChhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZywgY29uZmlnPzogeyBmb3JjZT86IGJvb2xlYW47IHJlYXNvbj86IHN0cmluZyB9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbGV0IGtleSA9IGAke2FjY291bnR9LyR7YnVja2V0TmFtZX1gO1xuICAgIGxldCBsb2FkZWQgPSBhd2FpdCBidWNrZXRzLmdldChrZXkpO1xuICAgIGlmICghbG9hZGVkKSByZXR1cm47XG4gICAgbGV0IHJvdXRpbmcgPSBhd2FpdCByZWFkUm91dGluZ0Zyb21EaXNrKGFjY291bnQsIGJ1Y2tldE5hbWUpO1xuICAgIGlmICghcm91dGluZykgcmV0dXJuO1xuICAgIGlmICghY29uZmlnPy5mb3JjZSAmJiBKU09OLnN0cmluZ2lmeShyb3V0aW5nKSA9PT0gbG9hZGVkLnJvdXRpbmdKU09OKSByZXR1cm47XG4gICAgbGV0IHJlYXNvbiA9IGNvbmZpZz8uZm9yY2UgJiYgKGNvbmZpZy5yZWFzb24gfHwgXCJmb3JjZWRcIikgfHwgXCJyb3V0aW5nIGNvbmZpZyBjaGFuZ2VkXCI7XG4gICAgbGV0IHBsYW4gPSBjb21wdXRlU3RvcmVQbGFuKGFjY291bnQsIGJ1Y2tldE5hbWUsIHJvdXRpbmcpO1xuICAgIGlmIChwbGFuLnN0cnVjdHVyZUtleSA9PT0gbG9hZGVkLnN0cnVjdHVyZUtleSkge1xuICAgICAgICBjb25zb2xlLmxvZyhgQXBwbHlpbmcgdGhlIHJvdXRpbmcgY29uZmlnIHRvIHRoZSBydW5uaW5nIHN0b3JlcyBmb3IgYnVja2V0ICR7a2V5fSAoJHtyZWFzb259KWApO1xuICAgICAgICBmb3IgKGxldCBwbGFuU3RvcmUgb2YgcGxhbi5zdG9yZXMpIHtcbiAgICAgICAgICAgIGxldCBsaXZlID0gbG9hZGVkLnN0b3Jlcy5maW5kKHggPT4geC5yb3V0ZUtleSA9PT0gcGxhblN0b3JlLnJvdXRlS2V5KTtcbiAgICAgICAgICAgIC8vIHN0cnVjdHVyZUtleSBlcXVhbGl0eSBtZWFucyB0aGUgc3RvcmUgc2V0IChyb3V0ZXMsIHJhd0Rpc2ssIGxpbWl0cykgaXMgdW5jaGFuZ2VkLCBzbyBldmVyeSBwbGFuIHN0b3JlIGhhcyBpdHMgbGl2ZSB0d2luXG4gICAgICAgICAgICBpZiAoIWxpdmUgfHwgIShsaXZlLnN0b3JlIGluc3RhbmNlb2YgQmxvYlN0b3JlKSkgY29udGludWU7XG4gICAgICAgICAgICBsZXQgc3RvcmVGb2xkZXIgPSBsaXZlLmZvbGRlcjtcbiAgICAgICAgICAgIGxpdmUuc3RvcmUudXBkYXRlU291cmNlcyhwbGFuU3RvcmUuc291cmNlU3BlY3MubWFwKHNwZWMgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHNvdXJjZUNvbmZpZyA9IHNwZWMuc291cmNlQ29uZmlnO1xuICAgICAgICAgICAgICAgIGlmICghc291cmNlQ29uZmlnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7IGlkZW50aXR5OiBzb3VyY2VJZGVudGl0eSh1bmRlZmluZWQpLCB1cmw6IHN0b3JlRm9sZGVyLCB2YWxpZFdpbmRvd3M6IHNwZWMudmFsaWRXaW5kb3dzLCBjcmVhdGU6ICgpOiBJQXJjaGl2ZXMgPT4gbmV3IEFyY2hpdmVzRGlzayhzdG9yZUZvbGRlcikgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgaWRlbnRpdHk6IHNvdXJjZUlkZW50aXR5KHNvdXJjZUNvbmZpZyksXG4gICAgICAgICAgICAgICAgICAgIHVybDogc291cmNlQ29uZmlnLnVybCxcbiAgICAgICAgICAgICAgICAgICAgdmFsaWRXaW5kb3dzOiBzcGVjLnZhbGlkV2luZG93cyxcbiAgICAgICAgICAgICAgICAgICAgcm91dGU6IHNwZWMucm91dGUsXG4gICAgICAgICAgICAgICAgICAgIG5vRnVsbFN5bmM6IHNwZWMubm9GdWxsU3luYyxcbiAgICAgICAgICAgICAgICAgICAgaW50ZXJtZWRpYXRlOiBzb3VyY2VDb25maWcuaW50ZXJtZWRpYXRlLFxuICAgICAgICAgICAgICAgICAgICBzb3VyY2VDb25maWcsXG4gICAgICAgICAgICAgICAgICAgIGNyZWF0ZTogKCkgPT4gY3JlYXRlQXBpQXJjaGl2ZXMoc291cmNlQ29uZmlnKSxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSksIHBsYW5TdG9yZS5lbnRyaWVzKTtcbiAgICAgICAgICAgIGxpdmUuZW50cmllcyA9IHBsYW5TdG9yZS5lbnRyaWVzO1xuICAgICAgICB9XG4gICAgICAgIGxvYWRlZC5yb3V0aW5nID0gcm91dGluZztcbiAgICAgICAgbG9hZGVkLnJvdXRpbmdKU09OID0gSlNPTi5zdHJpbmdpZnkocm91dGluZyk7XG4gICAgICAgIGxvYWRlZC5zZWxmRW50cmllcyA9IHBsYW4uc2VsZkVudHJpZXM7XG4gICAgICAgIGxvYWRlZC5zZWxmID0gcGxhbi5zZWxmO1xuICAgICAgICBzY2hlZHVsZVdpbmRvd0JvdW5kYXJ5UmVidWlsZChsb2FkZWQpO1xuICAgICAgICBzY2hlZHVsZUJvdW5kYXJ5U2NhbnMobG9hZGVkKTtcbiAgICAgICAgYnJvYWRjYXN0Um91dGluZ0NoYW5nZWQoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zb2xlLmxvZyhgUmVidWlsZGluZyB0aGUgc3RvcmVzIGZvciBidWNrZXQgJHtrZXl9ICgke3JlYXNvbn0pOiBzdHJ1Y3R1cmUgY2hhbmdlZCBmcm9tICR7bG9hZGVkLnN0cnVjdHVyZUtleX0gdG8gJHtwbGFuLnN0cnVjdHVyZUtleX1gKTtcbiAgICBmb3IgKGxldCBzIG9mIGxvYWRlZC5zdG9yZXMpIHtcbiAgICAgICAgaWYgKHMuc3RvcmUgaW5zdGFuY2VvZiBCbG9iU3RvcmUpIHtcbiAgICAgICAgICAgIGF3YWl0IHMuc3RvcmUuZGlzcG9zZSgpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGJ1Y2tldHMuc2V0KGtleSwgUHJvbWlzZS5yZXNvbHZlKGJ1aWxkQnVja2V0KGFjY291bnQsIGJ1Y2tldE5hbWUsIHJvdXRpbmcsIHBsYW4pKSk7XG4gICAgYnJvYWRjYXN0Um91dGluZ0NoYW5nZWQoKTtcbn1cblxuY29uc3Qgcm91dGluZ1dyaXRlcyA9IG5ldyBNYXA8c3RyaW5nLCBQcm9taXNlPHZvaWQ+PigpO1xuXG4vKiogVGhlIHJvdXRpbmctY29uZmlnIHdyaXRlIHBhdGggLSB0aGUgT05FIHdyaXRlIHRoYXQgY2Fubm90IGdvIHRocm91Z2ggYSBzdG9yZSAoaXQgaXMgd2hhdCBDUkVBVEVTIHRoZSBidWNrZXQgYW5kIGl0cyBzdG9yZXMpLiBTZXJpYWxpemVkIHBlciBidWNrZXQ6IGNvbmN1cnJlbnQgY29uZmlnIHdyaXRlcyB3b3VsZCByYWNlIHRoZSB2ZXJzaW9uIGNoZWNrLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHF1ZXVlUm91dGluZ0NvbmZpZ1dyaXRlKGFjY291bnQ6IHN0cmluZywgYnVja2V0TmFtZTogc3RyaW5nLCBkYXRhOiBCdWZmZXIsIGNvbmZpZz86IHsgbGFzdE1vZGlmaWVkPzogbnVtYmVyIH0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhc3NlcnRXcml0ZXNBbGxvd2VkKCk7XG4gICAgbGV0IGtleSA9IGAke2FjY291bnR9LyR7YnVja2V0TmFtZX1gO1xuICAgIGxldCBydW4gPSAocm91dGluZ1dyaXRlcy5nZXQoa2V5KSB8fCBQcm9taXNlLnJlc29sdmUoKSkudGhlbigoKSA9PiB3cml0ZVJvdXRpbmdDb25maWcoYWNjb3VudCwgYnVja2V0TmFtZSwgZGF0YSwgY29uZmlnKSk7XG4gICAgcm91dGluZ1dyaXRlcy5zZXQoa2V5LCBydW4udGhlbigoKSA9PiB7IH0sICgpID0+IHsgfSkpO1xuICAgIHJldHVybiBhd2FpdCBydW47XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHdyaXRlUm91dGluZ0NvbmZpZyhhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZywgZGF0YTogQnVmZmVyLCBjb25maWc/OiB7IGxhc3RNb2RpZmllZD86IG51bWJlciB9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbGV0IGtleSA9IGAke2FjY291bnR9LyR7YnVja2V0TmFtZX1gO1xuICAgIGxldCBpbmNvbWluZyA9IHBhcnNlUm91dGluZ0RhdGEoZGF0YSk7XG4gICAgbGV0IGxvYWRlZCA9IGF3YWl0IGdldExvYWRlZEJ1Y2tldChhY2NvdW50LCBidWNrZXROYW1lKTtcbiAgICBpZiAoIWxvYWRlZCkge1xuICAgICAgICBhd2FpdCByZXNvbHZlU291cmNlQXJjaGl2ZXMoZ2V0QnVja2V0Rm9sZGVyKGFjY291bnQsIGJ1Y2tldE5hbWUpKS5zZXQoUk9VVElOR19GSUxFLCBkYXRhLCB7IGxhc3RNb2RpZmllZDogY29uZmlnPy5sYXN0TW9kaWZpZWQgfSk7XG4gICAgICAgIGJ1Y2tldHMuc2V0KGtleSwgUHJvbWlzZS5yZXNvbHZlKGJ1aWxkQnVja2V0KGFjY291bnQsIGJ1Y2tldE5hbWUsIGluY29taW5nKSkpO1xuICAgICAgICBicm9hZGNhc3RSb3V0aW5nQ2hhbmdlZCgpO1xuICAgICAgICBjb25zb2xlLmxvZyhgQ3JlYXRlZCBidWNrZXQgJHtrZXl9YCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKEpTT04uc3RyaW5naWZ5KGluY29taW5nKSAhPT0gbG9hZGVkLnJvdXRpbmdKU09OICYmIGdldENvbmZpZ1ZlcnNpb24oaW5jb21pbmcpIDw9IGdldENvbmZpZ1ZlcnNpb24obG9hZGVkLnJvdXRpbmcpKSB7XG4gICAgICAgIGxldCBtZXNzYWdlID0gYENhbm5vdCB1cGRhdGUgcm91dGluZyBjb25maWcgZm9yIGJ1Y2tldCAke2tleX06IHRoZSBuZXcgY29uZmlnIGRpZmZlcnMgZnJvbSB0aGUgY3VycmVudCBvbmUgYnV0IGl0cyB2ZXJzaW9uICgke2dldENvbmZpZ1ZlcnNpb24oaW5jb21pbmcpfSkgaXMgbm90IGdyZWF0ZXIgdGhhbiB0aGUgY3VycmVudCB2ZXJzaW9uICgke2dldENvbmZpZ1ZlcnNpb24obG9hZGVkLnJvdXRpbmcpfSkuIEluY3JlbWVudCB0aGUgdmVyc2lvbiB0byB1cGRhdGUgaXQuIEN1cnJlbnQ6ICR7bG9hZGVkLnJvdXRpbmdKU09OfS4gQXR0ZW1wdGVkOiAke0pTT04uc3RyaW5naWZ5KGluY29taW5nKX1gO1xuICAgICAgICBjb25zb2xlLmVycm9yKG1lc3NhZ2UpO1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobWVzc2FnZSk7XG4gICAgfVxuICAgIGxldCBzdG9yZWQgPSBpbmNvbWluZztcbiAgICBsZXQgcmVpbmplY3RlZCA9IDA7XG4gICAgZm9yIChsZXQgaW50ZXJtZWRpYXRlIG9mIGdldEludGVybWVkaWF0ZVNvdXJjZXMoZXhwaXJlSW50ZXJtZWRpYXRlU291cmNlcyhsb2FkZWQucm91dGluZywgRGF0ZS5ub3coKSkpKSB7XG4gICAgICAgIHN0b3JlZCA9IGluamVjdEludGVybWVkaWF0ZVNvdXJjZShzdG9yZWQsIHtcbiAgICAgICAgICAgIHNwbGl0VXJsOiBpbnRlcm1lZGlhdGUuaW50ZXJtZWRpYXRlIHx8IGludGVybWVkaWF0ZS51cmwsXG4gICAgICAgICAgICBpbnRlcm1lZGlhdGVVcmw6IGludGVybWVkaWF0ZS51cmwsXG4gICAgICAgICAgICBzdGFydDogaW50ZXJtZWRpYXRlLnZhbGlkV2luZG93WzBdLFxuICAgICAgICAgICAgZW5kOiBpbnRlcm1lZGlhdGUudmFsaWRXaW5kb3dbMV0sXG4gICAgICAgIH0pO1xuICAgICAgICByZWluamVjdGVkKys7XG4gICAgfVxuICAgIGlmIChKU09OLnN0cmluZ2lmeShzdG9yZWQpICE9PSBKU09OLnN0cmluZ2lmeShpbmNvbWluZykpIHtcbiAgICAgICAgY29uc29sZS5sb2coYFJlLWluamVjdGVkICR7cmVpbmplY3RlZH0gaW4tZmxpZ2h0IHN3aXRjaG92ZXIgd2luZG93cyBpbnRvIHRoZSBpbmNvbWluZyByb3V0aW5nIGNvbmZpZyBmb3IgYnVja2V0ICR7a2V5fSAodmVyc2lvbiAke2dldENvbmZpZ1ZlcnNpb24oaW5jb21pbmcpfSlgKTtcbiAgICB9XG4gICAgLy8gV3JpdHRlbiBzdHJhaWdodCBpbnRvIHRoZSBwbGFpbiBidWNrZXQgZm9sZGVyOiB0aGUgcm91dGluZyBmaWxlIGRlZmluZXMgdGhlIHBlci1yb3V0ZSBzdG9yZXMsIHNvIGl0IG5ldmVyIGZsb3dzIHRocm91Z2ggdGhlbVxuICAgIGF3YWl0IHJlc29sdmVTb3VyY2VBcmNoaXZlcyhnZXRCdWNrZXRGb2xkZXIoYWNjb3VudCwgYnVja2V0TmFtZSkpLnNldChST1VUSU5HX0ZJTEUsIEJ1ZmZlci5mcm9tKHNlcmlhbGl6ZVJlbW90ZUNvbmZpZyhzdG9yZWQpKSwgeyBsYXN0TW9kaWZpZWQ6IGNvbmZpZz8ubGFzdE1vZGlmaWVkIH0pO1xuICAgIGF3YWl0IHNjaGVkdWxlUm91dGluZ1JlbG9hZChhY2NvdW50LCBidWNrZXROYW1lKTtcbn1cblxuLyoqIFdoaWNoIGJ1Y2tldHMgdGhpcyBwcm9jZXNzIGN1cnJlbnRseSBoYXMgbG9hZGVkIC0gd2hhdCBhIGRlcGxveSBzdWNjZXNzb3IgYXNrcyBpdHMgcHJlZGVjZXNzb3IgZm9yLCBzbyBpdCBhY3RpdmF0ZXMgZXhhY3RseSB0aGUgYnVja2V0cyB0aGF0IGFyZSBhY3R1YWxseSBpbiB1c2UuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0QWN0aXZlQnVja2V0S2V5cygpOiB7IGFjY291bnQ6IHN0cmluZzsgYnVja2V0TmFtZTogc3RyaW5nIH1bXSB7XG4gICAgcmV0dXJuIFsuLi5idWNrZXRzLmtleXMoKV0ubWFwKGtleSA9PiB7XG4gICAgICAgIGxldCBzbGFzaCA9IGtleS5pbmRleE9mKFwiL1wiKTtcbiAgICAgICAgcmV0dXJuIHsgYWNjb3VudDoga2V5LnNsaWNlKDAsIHNsYXNoKSwgYnVja2V0TmFtZToga2V5LnNsaWNlKHNsYXNoICsgMSkgfTtcbiAgICB9KTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYnVpbGRBbGxMb2FkZWRCdWNrZXRzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGZvciAobGV0IGtleSBvZiBbLi4uYnVja2V0cy5rZXlzKCldKSB7XG4gICAgICAgIGxldCBzbGFzaCA9IGtleS5pbmRleE9mKFwiL1wiKTtcbiAgICAgICAgYXdhaXQgc2NoZWR1bGVSb3V0aW5nUmVsb2FkKGtleS5zbGljZSgwLCBzbGFzaCksIGtleS5zbGljZShzbGFzaCArIDEpLCB7IGZvcmNlOiB0cnVlLCByZWFzb246IFwiYWxsIGxvYWRlZCBidWNrZXRzIHdlcmUgYXNrZWQgdG8gcmVidWlsZFwiIH0pO1xuICAgIH1cbn1cblxuY29uc3QgT1dOX0NPTkZJR19XUklURV9USFJPVFRMRSA9IDMwICogMTAwMDtcbmNvbnN0IElOVEVSTUVESUFURV9NQUlOVEFJTl9JTlRFUlZBTCA9IDYwICogMTAwMDtcbi8vIFBlciBidWNrZXQsIG5vdCBnbG9iYWw6IGEgc3dpdGNob3ZlciBoYXMgdG8gd3JpdGUgZXZlcnkgYnVja2V0J3Mgd2luZG93cyBhdCBvbmNlLCBhbmQgYSBzaGFyZWQgdGhyb3R0bGUgd291bGQgbGV0IG9ubHkgb25lIGJ1Y2tldCB0aHJvdWdoIHBlciBpbnRlcnZhbFxuY29uc3QgbGFzdE93bkNvbmZpZ1dyaXRlID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKTtcblxuYXN5bmMgZnVuY3Rpb24gd3JpdGVPd25Sb3V0aW5nQ29uZmlnKGxvYWRlZDogQnVja2V0U3RhdGUsIHVwZGF0ZWQ6IFJlbW90ZUNvbmZpZywgcmVhc29uOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsZXQga2V5ID0gYCR7bG9hZGVkLmFjY291bnR9LyR7bG9hZGVkLmJ1Y2tldE5hbWV9YDtcbiAgICBsZXQgc2luY2VMYXN0ID0gRGF0ZS5ub3coKSAtIChsYXN0T3duQ29uZmlnV3JpdGUuZ2V0KGtleSkgfHwgMCk7XG4gICAgaWYgKHNpbmNlTGFzdCA8IE9XTl9DT05GSUdfV1JJVEVfVEhST1RUTEUpIHtcbiAgICAgICAgY29uc29sZS5sb2coYE5vdCB3cml0aW5nIG91ciBvd24gcm91dGluZyBjb25maWcgdXBkYXRlIGZvciBidWNrZXQgJHtrZXl9ICgke3JlYXNvbn0pOiB0aGUgbGFzdCBvbmUgd2FzICR7c2luY2VMYXN0fW1zIGFnbywgdW5kZXIgdGhlICR7T1dOX0NPTkZJR19XUklURV9USFJPVFRMRX1tcyB0aHJvdHRsZS4gUmV0cnlpbmcgb24gdGhlIG5leHQgbWFpbnRlbmFuY2UgcGFzcy4gV2FudGVkOiAke0pTT04uc3RyaW5naWZ5KHVwZGF0ZWQpfWApO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGxhc3RPd25Db25maWdXcml0ZS5zZXQoa2V5LCBEYXRlLm5vdygpKTtcbiAgICBsZXQgdmVyc2lvbiA9IG5leHRJbnRlcm1lZGlhdGVWZXJzaW9uKGdldENvbmZpZ1ZlcnNpb24obG9hZGVkLnJvdXRpbmcpKTtcbiAgICBsZXQgbmV4dDogUmVtb3RlQ29uZmlnID0geyAuLi51cGRhdGVkLCB2ZXJzaW9uIH07XG4gICAgY29uc29sZS5sb2coYFdyaXRpbmcgJHtST1VUSU5HX0ZJTEV9IGZvciBidWNrZXQgJHtrZXl9ICgke3JlYXNvbn0pLCB2ZXJzaW9uICR7Z2V0Q29uZmlnVmVyc2lvbihsb2FkZWQucm91dGluZyl9IC0+ICR7dmVyc2lvbn06ICR7SlNPTi5zdHJpbmdpZnkobmV4dCl9YCk7XG4gICAgbGV0IGRhdGEgPSBCdWZmZXIuZnJvbShzZXJpYWxpemVSZW1vdGVDb25maWcobmV4dCkpO1xuICAgIGF3YWl0IHF1ZXVlUm91dGluZ0NvbmZpZ1dyaXRlKGxvYWRlZC5hY2NvdW50LCBsb2FkZWQuYnVja2V0TmFtZSwgZGF0YSk7XG4gICAgYXdhaXQgcHJvcGFnYXRlUm91dGluZ0NvbmZpZyhsb2FkZWQsIG5leHQsIGRhdGEpO1xufVxuXG5hc3luYyBmdW5jdGlvbiBwcm9wYWdhdGVSb3V0aW5nQ29uZmlnKGxvYWRlZDogQnVja2V0U3RhdGUsIG5leHQ6IFJlbW90ZUNvbmZpZywgZGF0YTogQnVmZmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbGV0IHRhcmdldHMgPSBuZXcgTWFwPHN0cmluZywgU291cmNlQ29uZmlnPigpO1xuICAgIGZvciAobGV0IHNvdXJjZSBvZiBbLi4ubG9hZGVkLnJvdXRpbmcuc291cmNlcywgLi4ubmV4dC5zb3VyY2VzXSkge1xuICAgICAgICBpZiAodHlwZW9mIHNvdXJjZSA9PT0gXCJzdHJpbmdcIiB8fCBzb3VyY2UuaW50ZXJtZWRpYXRlKSBjb250aW51ZTtcbiAgICAgICAgaWYgKHNvdXJjZS50eXBlID09PSBcInJlbW90ZVwiKSB7XG4gICAgICAgICAgICBsZXQgcGFyc2VkID0gcGFyc2VIb3N0ZWRVcmwoc291cmNlLnVybCk7XG4gICAgICAgICAgICBpZiAocGFyc2VkLmFjY291bnQgIT09IGxvYWRlZC5hY2NvdW50IHx8IHBhcnNlZC5idWNrZXROYW1lICE9PSBsb2FkZWQuYnVja2V0TmFtZSkgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRhcmdldHMuaGFzKHNvdXJjZS51cmwpKSBjb250aW51ZTtcbiAgICAgICAgdGFyZ2V0cy5zZXQoc291cmNlLnVybCwgc291cmNlKTtcbiAgICB9XG4gICAgZm9yIChsZXQgW3VybCwgc291cmNlXSBvZiB0YXJnZXRzKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBjcmVhdGVBcGlBcmNoaXZlcyhzb3VyY2UpLnNldChST1VUSU5HX0ZJTEUsIGRhdGEpO1xuICAgICAgICAgICAgY29uc29sZS5sb2coYFdyb3RlICR7Uk9VVElOR19GSUxFfSBmb3IgYnVja2V0ICR7bG9hZGVkLmFjY291bnR9LyR7bG9hZGVkLmJ1Y2tldE5hbWV9IHRvICR7dXJsfWApO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGBQcm9wYWdhdGluZyBvdXIgcm91dGluZyBjb25maWcgdXBkYXRlIHRvICR7dXJsfSBmYWlsZWQ6ICR7KGUgYXMgRXJyb3IpLnN0YWNrID8/IGV9YCk7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIG1haW50YWluSW50ZXJtZWRpYXRlcygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsZXQgeyBkb21haW4sIHBvcnQgfSA9IGdldFN0b3JhZ2VTZXJ2ZXJDb25maWcoKTtcbiAgICBsZXQgdGFrZW92ZXIgPSBnZXRUYWtlb3ZlckludGVybWVkaWF0ZSgpO1xuICAgIGxldCB3cml0dGVuOiBzdHJpbmdbXSA9IFtdO1xuICAgIGxldCBhbHJlYWR5Q29ycmVjdDogc3RyaW5nW10gPSBbXTtcbiAgICBsZXQgbm90T3Vyczogc3RyaW5nW10gPSBbXTtcbiAgICAvLyBPTkxZIGJ1Y2tldHMgYWxyZWFkeSBpbiBtZW1vcnkuIEEgc3dpdGNob3ZlciBtdXN0IG5ldmVyIGxvYWQgYSBidWNrZXQ6IGxvYWRpbmcgc3RhcnRzIGl0cyBzeW5jaHJvbml6YXRpb24sIGFuZCBidWNrZXRzIG5vdGhpbmcgaGFzIHRvdWNoZWQgKGxlZ2FjeSBvbmVzIGVzcGVjaWFsbHkpIGhhdmUgbm8gd3JpdGVzIHRvIGhhbmQgb2ZmIGluIHRoZSBmaXJzdCBwbGFjZS4gT25lIHRoYXQgZG9lcyBnZXQgdXNlZCBtaWQtc3dpdGNob3ZlciBsb2FkcyBvbiB0aGF0IGFjY2VzcywgYW5kIHRoZSBuZXh0IHBhc3MgZ2l2ZXMgaXQgaXRzIHdpbmRvdy5cbiAgICBsZXQga2V5cyA9IFsuLi5idWNrZXRzLmtleXMoKV07XG4gICAgZm9yIChsZXQga2V5IG9mIGtleXMpIHtcbiAgICAgICAgbGV0IGxvYWRlZFByb21pc2UgPSBidWNrZXRzLmdldChrZXkpO1xuICAgICAgICBpZiAoIWxvYWRlZFByb21pc2UpIGNvbnRpbnVlO1xuICAgICAgICBsZXQgbG9hZGVkID0gYXdhaXQgbG9hZGVkUHJvbWlzZS5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICAgICAgICBpZiAoIWxvYWRlZCkgY29udGludWU7XG4gICAgICAgIGxldCBleHBpcmVkID0gZXhwaXJlSW50ZXJtZWRpYXRlU291cmNlcyhsb2FkZWQucm91dGluZywgRGF0ZS5ub3coKSk7XG4gICAgICAgIGlmIChKU09OLnN0cmluZ2lmeShleHBpcmVkKSAhPT0gSlNPTi5zdHJpbmdpZnkobG9hZGVkLnJvdXRpbmcpKSB7XG4gICAgICAgICAgICBhd2FpdCB3cml0ZU93blJvdXRpbmdDb25maWcobG9hZGVkLCBleHBpcmVkLCBgc3dpdGNob3ZlciB3aW5kb3dzIGV4cGlyZWQgbW9yZSB0aGFuICR7SU5URVJNRURJQVRFX0VYUElSRV9HUkFDRSAvIDEwMDB9cyBhZ29gKTtcbiAgICAgICAgICAgIHdyaXR0ZW4ucHVzaChrZXkpO1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0YWtlb3ZlcikgY29udGludWU7XG4gICAgICAgIGxldCBtYWluVXJsID0gbG9hZGVkLnJvdXRpbmcuc291cmNlcy5maW5kKHggPT4ge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiB4ID09PSBcInN0cmluZ1wiIHx8IHgudHlwZSAhPT0gXCJyZW1vdGVcIiB8fCB4LmludGVybWVkaWF0ZSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgbGV0IHBhcnNlZCA9IHBhcnNlSG9zdGVkVXJsKHgudXJsKTtcbiAgICAgICAgICAgIHJldHVybiBwYXJzZWQuYWRkcmVzcyA9PT0gZG9tYWluICYmIHBhcnNlZC5wb3J0ID09PSBwb3J0O1xuICAgICAgICB9KSBhcyBIb3N0ZWRDb25maWcgfCB1bmRlZmluZWQ7XG4gICAgICAgIGlmICghbWFpblVybCkge1xuICAgICAgICAgICAgbm90T3Vycy5wdXNoKGtleSk7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgaW5qZWN0ZWQgPSBpbmplY3RJbnRlcm1lZGlhdGVTb3VyY2UobG9hZGVkLnJvdXRpbmcsIHtcbiAgICAgICAgICAgIHNwbGl0VXJsOiBtYWluVXJsLnVybCxcbiAgICAgICAgICAgIGludGVybWVkaWF0ZVVybDogcmVwbGFjZUhvc3RlZFVybFBvcnQobWFpblVybC51cmwsIHRha2VvdmVyLmFsdFBvcnQpLFxuICAgICAgICAgICAgc3RhcnQ6IHRha2VvdmVyLnN0YXJ0LFxuICAgICAgICAgICAgZW5kOiB0YWtlb3Zlci5lbmQsXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoSlNPTi5zdHJpbmdpZnkoaW5qZWN0ZWQpID09PSBKU09OLnN0cmluZ2lmeShsb2FkZWQucm91dGluZykpIHtcbiAgICAgICAgICAgIGFscmVhZHlDb3JyZWN0LnB1c2goa2V5KTtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG4gICAgICAgIGF3YWl0IHdyaXRlT3duUm91dGluZ0NvbmZpZyhsb2FkZWQsIGluamVjdGVkLCBgd2UgYXJlIGEgZGVwbG95IHN1Y2Nlc3Nvcjogd3JpdGVzIHJvdXRlIHRvIG91ciBhbHRlcm5hdGUgcG9ydCAke3Rha2VvdmVyLmFsdFBvcnR9IGZyb20gJHtuZXcgRGF0ZSh0YWtlb3Zlci5zdGFydCkudG9JU09TdHJpbmcoKX0gdW50aWwgb3VyIHByZWRlY2Vzc29yIGlzIGtpbGxlZCBhdCAke25ldyBEYXRlKHRha2VvdmVyLmVuZCkudG9JU09TdHJpbmcoKX1gKTtcbiAgICAgICAgd3JpdHRlbi5wdXNoKGtleSk7XG4gICAgfVxuICAgIGlmICghdGFrZW92ZXIpIHJldHVybjtcbiAgICBpZiAoIWtleXMubGVuZ3RoKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBObyBhY3RpdmUgYnVja2V0cywgc28gbm8gY29uZmlnIGZpbGVzIHRvIHdyaXRlIHRoZSBpbnRlcm1lZGlhdGUgaW50byAoYSBidWNrZXQgaXMgb25seSBhY3RpdmUgb25jZSBzb21ldGhpbmcgdXNlcyBpdClgKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoIXdyaXR0ZW4ubGVuZ3RoKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBXcm90ZSBubyBjb25maWcgZmlsZXM6IG9mICR7a2V5cy5sZW5ndGh9IGFjdGl2ZSBidWNrZXRzLCAke2FscmVhZHlDb3JyZWN0Lmxlbmd0aH0gYWxyZWFkeSBjb250YWluIHRoZSBpbnRlcm1lZGlhdGUgYW5kICR7bm90T3Vycy5sZW5ndGh9IGFyZSBub3QgaG9zdGVkIGJ5IHVzYCk7XG4gICAgfVxufVxuXG4vKiogT3VyIHByZWRlY2Vzc29yIHN0aWxsIGhvbGRzIHRoZSBtYWluIHBvcnQgYW5kIGhhcyBiZWVuIHNlcnZpbmcgYWxsIGFsb25nLCBzbyBpdCAtIG5vdCB1cyAtIGtub3dzIHdoaWNoIGJ1Y2tldHMgYXJlIGluIHVzZS4gV2UgYWN0aXZhdGUgZXhhY3RseSB0aG9zZSwgd2hpY2ggaXMgd2hhdCBtYWtlcyB0aGVpciBjb25maWcgZmlsZXMgZ2V0IHRoZSBpbnRlcm1lZGlhdGU7IG5vdGhpbmcgZWxzZSBvbiBkaXNrIGlzIHRvdWNoZWQuICovXG5hc3luYyBmdW5jdGlvbiBhY3RpdmF0ZVByZWRlY2Vzc29yQnVja2V0cygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBsZXQgeyBkb21haW4sIHBvcnQgfSA9IGdldFN0b3JhZ2VTZXJ2ZXJDb25maWcoKTtcbiAgICBsZXQgdXJsID0gYGh0dHBzOi8vJHtkb21haW59OiR7cG9ydH1gO1xuICAgIGxldCBrZXlzOiB7IGFjY291bnQ6IHN0cmluZzsgYnVja2V0TmFtZTogc3RyaW5nIH1bXTtcbiAgICB0cnkge1xuICAgICAgICBrZXlzID0gYXdhaXQgbGlzdFNlcnZlckFjdGl2ZUJ1Y2tldEtleXMoeyB1cmwgfSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKGBDb3VsZCBub3QgYXNrIG91ciBwcmVkZWNlc3NvciBvbiAke3VybH0gd2hpY2ggYnVja2V0cyBhcmUgYWN0aXZlLCBzbyBvbmx5IGJ1Y2tldHMgdXNlZCBvbiB0aGlzIHByb2Nlc3MgZ2V0IHRoZSBpbnRlcm1lZGlhdGU6ICR7KGUgYXMgRXJyb3IpLnN0YWNrID8/IGV9YCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKCFrZXlzLmxlbmd0aCkge1xuICAgICAgICBjb25zb2xlLmxvZyhgT3VyIHByZWRlY2Vzc29yIG9uICR7dXJsfSBoYXMgbm8gYWN0aXZlIGJ1Y2tldHMsIHNvIHRoZXJlIGFyZSBubyBjb25maWcgZmlsZXMgdG8gd3JpdGUgdGhlIGludGVybWVkaWF0ZSBpbnRvYCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc29sZS5sb2coYE91ciBwcmVkZWNlc3NvciBvbiAke3VybH0gaGFzICR7a2V5cy5sZW5ndGh9IGFjdGl2ZSBidWNrZXRzLCBhY3RpdmF0aW5nIHRoZW0gaGVyZSBzbyB0aGVpciBjb25maWcgZmlsZXMgZ2V0IHRoZSBpbnRlcm1lZGlhdGU6ICR7a2V5cy5tYXAoeCA9PiBgJHt4LmFjY291bnR9LyR7eC5idWNrZXROYW1lfWApLmpvaW4oXCIsIFwiKX1gKTtcbiAgICBmb3IgKGxldCB7IGFjY291bnQsIGJ1Y2tldE5hbWUgfSBvZiBrZXlzKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBhd2FpdCBnZXRMb2FkZWRCdWNrZXQoYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEFjdGl2YXRpbmcgYnVja2V0ICR7YWNjb3VudH0vJHtidWNrZXROYW1lfSAoYWN0aXZlIG9uIG91ciBwcmVkZWNlc3NvcikgZmFpbGVkOiAkeyhlIGFzIEVycm9yKS5zdGFjayA/PyBlfWApO1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vKiogU3RhcnRlZCBieSBkZXBsb3lUYWtlb3ZlciBvbmNlIHdlIGFyZSBhY3R1YWxseSBhIGRlcGxveSBzdWNjZXNzb3IgbGlzdGVuaW5nIG9uIGFuIGFsdGVybmF0ZSBwb3J0LiBVbnRpbCB0aGVuIHRoZXJlIGFyZSBubyBzd2l0Y2hvdmVyIHdpbmRvd3MgdG8gd3JpdGUgb3IgZXhwaXJlLCBzbyBub3RoaW5nIHBvbGxzLiAqL1xuZXhwb3J0IGNvbnN0IHN0YXJ0SW50ZXJtZWRpYXRlTWFpbnRlbmFuY2UgPSBsYXp5KCgpID0+IHtcbiAgICB2b2lkIChhc3luYyAoKSA9PiB7XG4gICAgICAgIGF3YWl0IGFjdGl2YXRlUHJlZGVjZXNzb3JCdWNrZXRzKCk7XG4gICAgICAgIGF3YWl0IG1haW50YWluSW50ZXJtZWRpYXRlcygpO1xuICAgIH0pKCkuY2F0Y2goKGU6IEVycm9yKSA9PiBjb25zb2xlLmVycm9yKGBXcml0aW5nIHRoZSBpbnRlcm1lZGlhdGUgaW50byB0aGUgY29uZmlnIGZpbGVzIGZhaWxlZDogJHtlLnN0YWNrID8/IGV9YCkpO1xuICAgIHJ1bkluZmluaXRlUG9sbChJTlRFUk1FRElBVEVfTUFJTlRBSU5fSU5URVJWQUwsIG1haW50YWluSW50ZXJtZWRpYXRlcyk7XG59KTtcblxuZXhwb3J0IHR5cGUgU2VydmVyQnVja2V0SW5mbyA9IHtcbiAgICBidWNrZXROYW1lOiBzdHJpbmc7XG4gICAgYWN0aXZlOiBib29sZWFuO1xuICAgIC8qKiBXaGVyZSB0aGUgYnVja2V0J3MgZGF0YSBsaXZlcyBvbiB0aGlzIHNlcnZlciAqL1xuICAgIGZvbGRlcjogc3RyaW5nO1xuICAgIC8qKiBUaGUgZHJpdmUgdGhhdCBmb2xkZXIgaXMgb24uIEJ1Y2tldHMgc2hhcmluZyBhIGRyaXZlIHJlcG9ydCB0aGUgc2FtZSBudW1iZXJzLiAqL1xuICAgIGRpc2s/OiBCdWNrZXREaXNrSW5mbztcbiAgICBkaXNrRXJyb3I/OiBzdHJpbmc7XG4gICAgd3JpdGVTdGF0cz86IEJ1Y2tldFdyaXRlU3RhdHM7XG4gICAgY29uZmlnPzogQXJjaGl2ZXNDb25maWc7XG4gICAgZXJyb3I/OiBzdHJpbmc7XG59O1xuXG5leHBvcnQgdHlwZSBBY3RpdmVCdWNrZXRJbmZvID0ge1xuICAgIGZvbGRlcjogc3RyaW5nO1xuICAgIC8qKiBUaGUgcm91dGluZyBjb25maWcgdGhlIGJ1Y2tldCBpcyBSVU5OSU5HIG9uLCBzdHJhaWdodCBmcm9tIG1lbW9yeSAtIGluY2x1ZGluZyBzd2l0Y2hvdmVyIHdpbmRvd3Mgd3JpdHRlbiBzaW5jZSBpdCBsb2FkZWQgKi9cbiAgICByb3V0aW5nOiBSZW1vdGVDb25maWc7XG4gICAgLyoqIE91ciBvd24gZW50cmllcyBpbiB0aGF0IGNvbmZpZywgYW5kIHRoZWlyIHN1bW1hcml6ZWQgY3VycmVudCByb2xlIChyb3V0ZXMgdW5pb24gKyBmbGFncykgKi9cbiAgICBzZWxmRW50cmllczogSG9zdGVkQ29uZmlnW107XG4gICAgc2VsZj86IFNlbGZTdW1tYXJ5O1xuICAgIGNvbmZpZzogQXJjaGl2ZXNDb25maWc7XG59O1xuXG5mdW5jdGlvbiB0b0FjdGl2ZUJ1Y2tldEluZm8obG9hZGVkOiBCdWNrZXRTdGF0ZSk6IEFjdGl2ZUJ1Y2tldEluZm8ge1xuICAgIHJldHVybiB7XG4gICAgICAgIGZvbGRlcjogZ2V0QnVja2V0Rm9sZGVyKGxvYWRlZC5hY2NvdW50LCBsb2FkZWQuYnVja2V0TmFtZSksXG4gICAgICAgIHJvdXRpbmc6IGxvYWRlZC5yb3V0aW5nLFxuICAgICAgICBzZWxmRW50cmllczogbG9hZGVkLnNlbGZFbnRyaWVzLFxuICAgICAgICBzZWxmOiBsb2FkZWQuc2VsZixcbiAgICAgICAgY29uZmlnOiBnZXRCdWNrZXRDb25maWcobG9hZGVkKSxcbiAgICB9O1xufVxuXG4vKiogVGhlIGxpdmUgaW4tbWVtb3J5IHN0YXRlIG9mIE9ORSBidWNrZXQsIGFuc3dlcmVkIHdpdGhvdXQgdG91Y2hpbmcgdGhlIGRpc2sgKG5vIHJvdXRpbmcgZmlsZSByZWFkLCBubyBzdGF0ZnMsIG5vIHN0b3JlZCB3cml0ZSBzdGF0cykuIFJldHVybnMgYW4gZXJyb3Igc3RyaW5nIHdoZW4gdGhlIGJ1Y2tldCBpcyBub3QgbG9hZGVkIGhlcmUsIHdoaWNoIGlzIHRoZSBub3JtYWwgc3RhdGUgZm9yIGEgYnVja2V0IG5vdGhpbmcgaGFzIGFjY2Vzc2VkIHNpbmNlIHN0YXJ0dXAuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0QWN0aXZlQnVja2V0KGFjY291bnQ6IHN0cmluZywgYnVja2V0TmFtZTogc3RyaW5nKTogUHJvbWlzZTxBY3RpdmVCdWNrZXRJbmZvIHwgc3RyaW5nPiB7XG4gICAgbGV0IGtleSA9IGAke2FjY291bnR9LyR7YnVja2V0TmFtZX1gO1xuICAgIGxldCBsb2FkZWRQcm9taXNlID0gYnVja2V0cy5nZXQoa2V5KTtcbiAgICBpZiAoIWxvYWRlZFByb21pc2UpIHtcbiAgICAgICAgcmV0dXJuIGBCdWNrZXQgJHtrZXl9IGlzIG5vdCBsb2FkZWQgb24gdGhpcyBzZXJ2ZXIsIHNvIGl0IGhhcyBubyBsaXZlIHN0YXRlIChpdCBsb2FkcyBvbiBmaXJzdCBhY2Nlc3MpYDtcbiAgICB9XG4gICAgbGV0IGxvYWRlZDogQnVja2V0U3RhdGUgfCB1bmRlZmluZWQ7XG4gICAgdHJ5IHtcbiAgICAgICAgbG9hZGVkID0gYXdhaXQgbG9hZGVkUHJvbWlzZTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHJldHVybiBgQnVja2V0ICR7a2V5fSBmYWlsZWQgdG8gbG9hZCBvbiB0aGlzIHNlcnZlcjogJHtTdHJpbmcoKGUgYXMgRXJyb3IpLnN0YWNrID8/IGUpLnNsaWNlKDAsIDUwMCl9YDtcbiAgICB9XG4gICAgaWYgKCFsb2FkZWQpIHtcbiAgICAgICAgcmV0dXJuIGBCdWNrZXQgJHtrZXl9IGRvZXMgbm90IGV4aXN0IG9uIHRoaXMgc2VydmVyYDtcbiAgICB9XG4gICAgcmV0dXJuIHRvQWN0aXZlQnVja2V0SW5mbyhsb2FkZWQpO1xufVxuXG4vKiogTG9hZHMgYSBidWNrZXQgdGhhdCBleGlzdHMgb24gdGhpcyBzZXJ2ZXIncyBkaXNrIGludG8gbWVtb3J5LCB3aGljaCBzdGFydHMgaXRzIHN5bmNocm9uaXphdGlvbiBhbmQgd2luZG93IHRpbWVycywgYW5kIHJldHVybnMgaXRzIGxpdmUgc3RhdGUuIE5vdGhpbmcgaXMgd3JpdHRlbiBhbmQgbm8gb3RoZXIgc2VydmVyIGlzIGNvbnRhY3RlZCAtIHVubGlrZSBidWlsZGluZyBhbiBBcmNoaXZlc0NoYWluIGZvciBpdCwgd2hpY2ggd291bGQgcHJvYmUgZXZlcnkgc291cmNlIGFuZCBjb3VsZCB3cml0ZSB0aGUgcm91dGluZyBjb25maWcuIEFscmVhZHktbG9hZGVkIGJ1Y2tldHMganVzdCByZXR1cm4gdGhlaXIgc3RhdGUuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYWN0aXZhdGVCdWNrZXQoYWNjb3VudDogc3RyaW5nLCBidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPEFjdGl2ZUJ1Y2tldEluZm8gfCBzdHJpbmc+IHtcbiAgICBsZXQga2V5ID0gYCR7YWNjb3VudH0vJHtidWNrZXROYW1lfWA7XG4gICAgbGV0IHdhc0xvYWRlZCA9IGJ1Y2tldHMuaGFzKGtleSk7XG4gICAgbGV0IGxvYWRlZDogQnVja2V0U3RhdGUgfCB1bmRlZmluZWQ7XG4gICAgdHJ5IHtcbiAgICAgICAgbG9hZGVkID0gYXdhaXQgZ2V0TG9hZGVkQnVja2V0KGFjY291bnQsIGJ1Y2tldE5hbWUpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmV0dXJuIGBCdWNrZXQgJHtrZXl9IGZhaWxlZCB0byBsb2FkIG9uIHRoaXMgc2VydmVyOiAke1N0cmluZygoZSBhcyBFcnJvcikuc3RhY2sgPz8gZSkuc2xpY2UoMCwgNTAwKX1gO1xuICAgIH1cbiAgICBpZiAoIWxvYWRlZCkge1xuICAgICAgICByZXR1cm4gYEJ1Y2tldCAke2tleX0gZG9lcyBub3QgZXhpc3Qgb24gdGhpcyBzZXJ2ZXIgKG5vIHJvdXRpbmcgZmlsZSBpbiAke2dldEJ1Y2tldEZvbGRlcihhY2NvdW50LCBidWNrZXROYW1lKX0pYDtcbiAgICB9XG4gICAgLy8gV2FpdCBmb3IgdGhlIGluZGV4ZXMgdG8gbG9hZCwgc28gdGhlIHRvdGFscyB3ZSByZXR1cm4gYXJlIHRoZSByZWFsIG9uZXMgcmF0aGVyIHRoYW4gemVyb2VzIGZyb20gc3RvcmVzIHRoYXQgaGF2ZSBub3QgcmVhZCB0aGVpciBpbmRleCB5ZXQuIFRoZSBzb3VyY2Ugc2NhbnMga2VlcCBydW5uaW5nIGluIHRoZSBiYWNrZ3JvdW5kLlxuICAgIGZvciAobGV0IHMgb2YgbG9hZGVkLnN0b3Jlcykge1xuICAgICAgICBpZiAocy5zdG9yZSBpbnN0YW5jZW9mIEJsb2JTdG9yZSkge1xuICAgICAgICAgICAgYXdhaXQgcy5zdG9yZS5pbml0KCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKCF3YXNMb2FkZWQpIHtcbiAgICAgICAgY29uc29sZS5sb2coYEFjdGl2YXRlZCBidWNrZXQgJHtrZXl9IG9uIHJlcXVlc3Q6IGl0IGlzIG5vdyBsb2FkZWQgYW5kIHN5bmNocm9uaXppbmdgKTtcbiAgICB9XG4gICAgcmV0dXJuIHRvQWN0aXZlQnVja2V0SW5mbyhsb2FkZWQpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbGlzdEFjY291bnRCdWNrZXRzKGFjY291bnQ6IHN0cmluZyk6IFByb21pc2U8U2VydmVyQnVja2V0SW5mb1tdPiB7XG4gICAgbGV0IHN0YXJ0ID0gRGF0ZS5ub3coKTtcbiAgICBsZXQgdGltaW5ncyA9IG5ldyBNYXA8c3RyaW5nLCBudW1iZXI+KCk7XG4gICAgYXN5bmMgZnVuY3Rpb24gdGltZWQ8VD4obmFtZTogc3RyaW5nLCBydW46ICgpID0+IFByb21pc2U8VD4pOiBQcm9taXNlPFQ+IHtcbiAgICAgICAgbGV0IGJlZ2FuID0gRGF0ZS5ub3coKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJldHVybiBhd2FpdCBydW4oKTtcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgIHRpbWluZ3Muc2V0KG5hbWUsICh0aW1pbmdzLmdldChuYW1lKSB8fCAwKSArIChEYXRlLm5vdygpIC0gYmVnYW4pKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBsZXQgYWNjb3VudEZvbGRlciA9IHBhdGguam9pbihnZXRTdG9yYWdlU2VydmVyQ29uZmlnKCkuZm9sZGVyLCBcImJ1Y2tldHMyXCIsIGFjY291bnQpO1xuICAgIGxldCBuYW1lczogc3RyaW5nW107XG4gICAgdHJ5IHtcbiAgICAgICAgbmFtZXMgPSBhd2FpdCB0aW1lZChcInJlYWRkaXJcIiwgKCkgPT4gZnMucHJvbWlzZXMucmVhZGRpcihhY2NvdW50Rm9sZGVyKSk7XG4gICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiBbXTtcbiAgICB9XG4gICAgLy8gUGVyLXJvdXRlIGZvbGRlcnMgKGJ1Y2tldE5hbWUtcm91dGUtPHN0YXJ0Pi08ZW5kPikgYmVsb25nIHRvIHRoZSBzYW1lIGJ1Y2tldCBhcyB0aGUgcGxhaW4gZm9sZGVyIC0gY29sbGFwc2UgdGhlbSBzbyBvbmUgYnVja2V0IGxpc3RzIG9uY2VcbiAgICBuYW1lcyA9IFsuLi5uZXcgU2V0KG5hbWVzLm1hcCh4ID0+IHgucmVwbGFjZSgvLXJvdXRlLVtcXGQuXSstW1xcZC5dKyQvLCBcIlwiKSkpXTtcbiAgICB0cnkge1xuICAgICAgICByZXR1cm4gYXdhaXQgUHJvbWlzZS5hbGwobmFtZXMubWFwKGFzeW5jIGJ1Y2tldE5hbWUgPT4ge1xuICAgICAgICAgICAgbGV0IGtleSA9IGAke2FjY291bnR9LyR7YnVja2V0TmFtZX1gO1xuICAgICAgICAgICAgbGV0IGZvbGRlciA9IGdldEJ1Y2tldEZvbGRlcihhY2NvdW50LCBidWNrZXROYW1lKTtcbiAgICAgICAgICAgIGxldCBiYXNlOiBTZXJ2ZXJCdWNrZXRJbmZvID0geyBidWNrZXROYW1lLCBhY3RpdmU6IGZhbHNlLCBmb2xkZXIgfTtcbiAgICAgICAgICAgIGJhc2UuZGlzayA9IGF3YWl0IHRpbWVkKFwic3RhdGZzXCIsICgpID0+IGdldERpc2tJbmZvKGZvbGRlcikpLmNhdGNoKChlOiBFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIGJhc2UuZGlza0Vycm9yID0gU3RyaW5nKGUuc3RhY2sgPz8gZSkuc2xpY2UoMCwgNTAwKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBiYXNlLndyaXRlU3RhdHMgPSBnZXRCdWNrZXRXcml0ZVN0YXRzKGtleSk7XG4gICAgICAgICAgICBjb25zdCBsb2FkZWRQcm9taXNlID0gYnVja2V0cy5nZXQoa2V5KTtcbiAgICAgICAgICAgIGlmIChsb2FkZWRQcm9taXNlKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGxvYWRlZCA9IGF3YWl0IHRpbWVkKFwiYXdhaXRMb2FkZWRcIiwgKCkgPT4gbG9hZGVkUHJvbWlzZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChsb2FkZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7IC4uLmJhc2UsIGFjdGl2ZTogdHJ1ZSwgY29uZmlnOiBnZXRCdWNrZXRDb25maWcobG9hZGVkKSB9O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4geyAuLi5iYXNlLCBhY3RpdmU6IHRydWUsIGVycm9yOiBTdHJpbmcoKGUgYXMgRXJyb3IpLnN0YWNrID8/IGUpLnNsaWNlKDAsIDUwMCkgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCB0aW1lZChcInJlYWRSb3V0aW5nRmlsZVwiLCAoKSA9PiByZWFkUm91dGluZ0ZpbGUoZm9sZGVyKSk7XG4gICAgICAgICAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7IC4uLmJhc2UsIGVycm9yOiBgTm8gcm91dGluZyBmaWxlICgke1JPVVRJTkdfRklMRX0pYCB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsZXQgcGFyc2VkID0gYXdhaXQgdGltZWQoXCJwYXJzZVJvdXRpbmdcIiwgYXN5bmMgKCkgPT4gcGFyc2VSb3V0aW5nRGF0YShkYXRhKSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgLi4uYmFzZSwgY29uZmlnOiB7IHJlbW90ZUNvbmZpZzogcGFyc2VkIH0gfTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geyAuLi5iYXNlLCBlcnJvcjogU3RyaW5nKChlIGFzIEVycm9yKS5zdGFjayA/PyBlKS5zbGljZSgwLCA1MDApIH07XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pKTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgICAvLyBUaGUgcGFydHMgcnVuIGNvbmN1cnJlbnRseSwgc28gdGhlc2UgYXJlIHN1bW1lZCB3YWxsIHRpbWVzIHBlciBwYXJ0LCBub3QgYSBicmVha2Rvd24gb2YgdGhlIHRvdGFsXG4gICAgICAgIGxldCBwYXJ0cyA9IFsuLi50aW1pbmdzXS5tYXAoKFtuYW1lLCBtc10pID0+IGAke25hbWV9ICR7bXN9bXNgKS5qb2luKFwiLCBcIik7XG4gICAgICAgIGNvbnNvbGUubG9nKGBsaXN0QWNjb3VudEJ1Y2tldHMoJHthY2NvdW50fSkgdG9vayAke0RhdGUubm93KCkgLSBzdGFydH1tcyBmb3IgJHtuYW1lcy5sZW5ndGh9IGJ1Y2tldHM6ICR7cGFydHN9YCk7XG4gICAgfVxufVxuXG5leHBvcnQgdHlwZSBCdWNrZXRXcml0ZVN0YXRzID0ge1xuICAgIC8qKiBFdmVyeSBzZXQgY2FsbCB0aGUgYnVja2V0IGFjY2VwdGVkICovXG4gICAgb3JpZ2luYWxXcml0ZXM6IG51bWJlcjtcbiAgICBvcmlnaW5hbEJ5dGVzOiBudW1iZXI7XG4gICAgLyoqIFdoYXQgYWN0dWFsbHkgcmVhY2hlZCB0aGUgc291cmNlcy4gRmFzdCB3cml0ZXMgY29hbGVzY2UgcmVwZWF0ZWQgd3JpdGVzIHRvIHRoZSBzYW1lIGtleSwgc28gdGhpcyBpcyBsb3dlciB0aGFuIHRoZSBvcmlnaW5hbCBjb3VudHMgKGFuZCBpcyB3aGF0IHRoZSBkaXNrIGFjdHVhbGx5IGRpZCkuICovXG4gICAgZmx1c2hlZFdyaXRlczogbnVtYmVyO1xuICAgIGZsdXNoZWRCeXRlczogbnVtYmVyO1xufTtcbmZ1bmN0aW9uIGVtcHR5V3JpdGVTdGF0cygpOiBCdWNrZXRXcml0ZVN0YXRzIHtcbiAgICByZXR1cm4geyBvcmlnaW5hbFdyaXRlczogMCwgb3JpZ2luYWxCeXRlczogMCwgZmx1c2hlZFdyaXRlczogMCwgZmx1c2hlZEJ5dGVzOiAwIH07XG59XG5cbi8vIEluIG1lbW9yeSBvbmx5OiB0b3RhbHMgc2luY2UgdGhpcyBwcm9jZXNzIHN0YXJ0ZWQgKG9yIHRoZSBsYXN0IGNsZWFyV3JpdGVTdGF0cykuIFBlcnNpc3RpbmcgdGhlbSB0byBkaXNrIHdhcyBtb3JlIG1hY2hpbmVyeSB0aGFuIHRoZSBudW1iZXJzIHdlcmUgd29ydGguXG5jb25zdCB3cml0ZVN0YXRzID0gbmV3IE1hcDxzdHJpbmcsIEJ1Y2tldFdyaXRlU3RhdHM+KCk7XG5cbmZ1bmN0aW9uIGNvdW50QnVja2V0V3JpdGUoa2V5OiBzdHJpbmcsIGtpbmQ6IFwib3JpZ2luYWxcIiB8IFwiZmx1c2hlZFwiLCBieXRlczogbnVtYmVyKTogdm9pZCB7XG4gICAgbGV0IHN0YXRzID0gd3JpdGVTdGF0cy5nZXQoa2V5KTtcbiAgICBpZiAoIXN0YXRzKSB7XG4gICAgICAgIHN0YXRzID0gZW1wdHlXcml0ZVN0YXRzKCk7XG4gICAgICAgIHdyaXRlU3RhdHMuc2V0KGtleSwgc3RhdHMpO1xuICAgIH1cbiAgICBpZiAoa2luZCA9PT0gXCJvcmlnaW5hbFwiKSB7XG4gICAgICAgIHN0YXRzLm9yaWdpbmFsV3JpdGVzKys7XG4gICAgICAgIHN0YXRzLm9yaWdpbmFsQnl0ZXMgKz0gYnl0ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgc3RhdHMuZmx1c2hlZFdyaXRlcysrO1xuICAgICAgICBzdGF0cy5mbHVzaGVkQnl0ZXMgKz0gYnl0ZXM7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBnZXRCdWNrZXRXcml0ZVN0YXRzKGtleTogc3RyaW5nKTogQnVja2V0V3JpdGVTdGF0cyB7XG4gICAgcmV0dXJuIHdyaXRlU3RhdHMuZ2V0KGtleSkgfHwgZW1wdHlXcml0ZVN0YXRzKCk7XG59XG5cbi8qKiBaZXJvZXMgdGhlIHdyaXRlIHN0YXRpc3RpY3Mgb2YgZXZlcnkgYnVja2V0IGluIHRoZSBhY2NvdW50LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsZWFyQWNjb3VudFdyaXRlU3RhdHMoYWNjb3VudDogc3RyaW5nKTogbnVtYmVyIHtcbiAgICBsZXQgcHJlZml4ID0gYCR7YWNjb3VudH0vYDtcbiAgICBsZXQgY2xlYXJlZCA9IDA7XG4gICAgZm9yIChsZXQga2V5IG9mIFsuLi53cml0ZVN0YXRzLmtleXMoKV0pIHtcbiAgICAgICAgaWYgKCFrZXkuc3RhcnRzV2l0aChwcmVmaXgpKSBjb250aW51ZTtcbiAgICAgICAgd3JpdGVTdGF0cy5kZWxldGUoa2V5KTtcbiAgICAgICAgY2xlYXJlZCsrO1xuICAgIH1cbiAgICBjb25zb2xlLmxvZyhgQ2xlYXJlZCB0aGUgd3JpdGUgc3RhdGlzdGljcyBvZiAke2NsZWFyZWR9IGJ1Y2tldHMgaW4gYWNjb3VudCAke2FjY291bnR9YCk7XG4gICAgcmV0dXJuIGNsZWFyZWQ7XG59XG5cbmNvbnN0IExBUkdFX0ZJTEVfUEFSVF9TSVpFID0gOCAqIDEwMjQgKiAxMDI0O1xuXG4vLyBXcmFwcyBhIGxvY2FsbHkgaG9zdGVkIGJ1Y2tldCBpbiB0aGUgSUFyY2hpdmVzIGludGVyZmFjZSwgc28gY29kZSB3cml0dGVuIGFnYWluc3QgSUFyY2hpdmVzICh0aGUgY2hhaW4sIHN5bmMgc291cmNlcywgaG9sZGVyIHJlYWRzKSB0YWxrcyB0byBpdCBkaXJlY3RseSBpbnN0ZWFkIG9mIGJlY29taW5nIGEgbmV0d29yayBjbGllbnQgdG8gb3Vyc2VsdmVzLlxuY2xhc3MgQnVja2V0SUFyY2hpdmVzV3JhcHBlciBpbXBsZW1lbnRzIElBcmNoaXZlcyB7XG4gICAgY29uc3RydWN0b3IocHJpdmF0ZSBhY2NvdW50OiBzdHJpbmcsIHByaXZhdGUgYnVja2V0TmFtZTogc3RyaW5nLCBwcml2YXRlIHNvdXJjZUNvbmZpZzogU291cmNlQ29uZmlnKSB7IH1cblxuICAgIHByaXZhdGUgZmluZFN0b3JlKCk6IFByb21pc2U8TG9hZGVkU3RvcmU+IHtcbiAgICAgICAgcmV0dXJuIGZpbmRCdWNrZXRTdG9yZSh0aGlzLmFjY291bnQsIHRoaXMuYnVja2V0TmFtZSwgdGhpcy5zb3VyY2VDb25maWcpO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXREZWJ1Z05hbWUoKSB7XG4gICAgICAgIHJldHVybiBgbG9jYWxCdWNrZXQgYWNjb3VudCAke3RoaXMuYWNjb3VudH0gYnVja2V0ICR7dGhpcy5idWNrZXROYW1lfSByb3V0ZSAke0pTT04uc3RyaW5naWZ5KHRoaXMuc291cmNlQ29uZmlnLnJvdXRlIHx8IEZVTExfUk9VVEUpfWA7XG4gICAgfVxuICAgIHB1YmxpYyBhc3luYyBnZXQoZmlsZU5hbWU6IHN0cmluZywgY29uZmlnPzogR2V0Q29uZmlnKTogUHJvbWlzZTxCdWZmZXIgfCB1bmRlZmluZWQ+IHtcbiAgICAgICAgbGV0IHJlc3VsdCA9IGF3YWl0IHRoaXMuZ2V0MihmaWxlTmFtZSwgY29uZmlnKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCAmJiByZXN1bHQuZGF0YSB8fCB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHB1YmxpYyBhc3luYyBnZXQyKGZpbGVOYW1lOiBzdHJpbmcsIGNvbmZpZz86IEdldENvbmZpZyk6IFByb21pc2U8eyBkYXRhOiBCdWZmZXI7IHdyaXRlVGltZTogbnVtYmVyOyBzaXplOiBudW1iZXIgfSB8IHVuZGVmaW5lZD4ge1xuICAgICAgICBpZiAoZmlsZU5hbWUgPT09IFJPVVRJTkdfRklMRSkge1xuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IGdldFJvdXRpbmdGaWxlUmVzdWx0KHRoaXMuYWNjb3VudCwgdGhpcy5idWNrZXROYW1lKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY29uZmlnPy5pbnRlcm5hbCkge1xuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHJlYWRCdWNrZXRJbnRlcm5hbCh0aGlzLmFjY291bnQsIHRoaXMuYnVja2V0TmFtZSwgeyBwYXRoOiBmaWxlTmFtZSwgcmFuZ2U6IGNvbmZpZy5yYW5nZSwgaW5jbHVkZVRvbWJzdG9uZXM6IGNvbmZpZy5pbmNsdWRlVG9tYnN0b25lcyB9KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYXdhaXQgKGF3YWl0IHRoaXMuZmluZFN0b3JlKCkpLnN0b3JlLmdldDIoeyBwYXRoOiBmaWxlTmFtZSwgLi4uY29uZmlnIH0pO1xuICAgIH1cbiAgICBwdWJsaWMgYXN5bmMgc2V0KGZpbGVOYW1lOiBzdHJpbmcsIGRhdGE6IEJ1ZmZlciwgY29uZmlnPzogU2V0Q29uZmlnKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICAgICAgYXNzZXJ0V3JpdGVzQWxsb3dlZCgpO1xuICAgICAgICBpZiAoZmlsZU5hbWUgPT09IFJPVVRJTkdfRklMRSkge1xuICAgICAgICAgICAgYXdhaXQgcXVldWVSb3V0aW5nQ29uZmlnV3JpdGUodGhpcy5hY2NvdW50LCB0aGlzLmJ1Y2tldE5hbWUsIGRhdGEsIGNvbmZpZyk7XG4gICAgICAgICAgICByZXR1cm4gZmlsZU5hbWU7XG4gICAgICAgIH1cbiAgICAgICAgYXdhaXQgKGF3YWl0IHRoaXMuZmluZFN0b3JlKCkpLnN0b3JlLnNldCh7IC4uLmNvbmZpZywgcGF0aDogZmlsZU5hbWUsIGRhdGEgfSk7XG4gICAgICAgIHJldHVybiBmaWxlTmFtZTtcbiAgICB9XG4gICAgcHVibGljIGFzeW5jIGRlbChmaWxlTmFtZTogc3RyaW5nLCBjb25maWc/OiBEZWxDb25maWcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgYXNzZXJ0V3JpdGVzQWxsb3dlZCgpO1xuICAgICAgICBhd2FpdCAoYXdhaXQgdGhpcy5maW5kU3RvcmUoKSkuc3RvcmUuZGVsKHsgcGF0aDogZmlsZU5hbWUsIC4uLmNvbmZpZyB9KTtcbiAgICB9XG4gICAgcHVibGljIGFzeW5jIHNldExhcmdlRmlsZShjb25maWc6IHsgcGF0aDogc3RyaW5nOyBsYXN0TW9kaWZpZWQ/OiBudW1iZXI7IGdldE5leHREYXRhKCk6IFByb21pc2U8QnVmZmVyIHwgdW5kZWZpbmVkPiB9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIGFzc2VydFdyaXRlc0FsbG93ZWQoKTtcbiAgICAgICAgbGV0IHN0b3JlID0gKGF3YWl0IHRoaXMuZmluZFN0b3JlKCkpLnN0b3JlO1xuICAgICAgICBsZXQgaWQgPSBhd2FpdCBzdG9yZS5zdGFydExhcmdlVXBsb2FkKHsgcGF0aDogY29uZmlnLnBhdGgsIGxhc3RNb2RpZmllZDogY29uZmlnLmxhc3RNb2RpZmllZCB9KTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgICAgICAgICAgbGV0IGRhdGEgPSBhd2FpdCBjb25maWcuZ2V0TmV4dERhdGEoKTtcbiAgICAgICAgICAgICAgICBpZiAoIWRhdGEpIGJyZWFrO1xuICAgICAgICAgICAgICAgIGZvciAobGV0IG9mZnNldCA9IDA7IG9mZnNldCA8IGRhdGEubGVuZ3RoOyBvZmZzZXQgKz0gTEFSR0VfRklMRV9QQVJUX1NJWkUpIHtcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgc3RvcmUuYXBwZW5kTGFyZ2VVcGxvYWQoeyBpZCwgZGF0YTogZGF0YS5zdWJhcnJheShvZmZzZXQsIG9mZnNldCArIExBUkdFX0ZJTEVfUEFSVF9TSVpFKSB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhd2FpdCBzdG9yZS5maW5pc2hMYXJnZVVwbG9hZCh7IGlkLCBwYXRoOiBjb25maWcucGF0aCwgbGFzdE1vZGlmaWVkOiBjb25maWcubGFzdE1vZGlmaWVkIH0pO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBhd2FpdCBzdG9yZS5jYW5jZWxMYXJnZVVwbG9hZCh7IGlkIH0pO1xuICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBwdWJsaWMgYXN5bmMgZ2V0SW5mbyhmaWxlTmFtZTogc3RyaW5nLCBjb25maWc/OiBHZXRJbmZvQ29uZmlnKTogUHJvbWlzZTx7IHdyaXRlVGltZTogbnVtYmVyOyBzaXplOiBudW1iZXIgfSB8IHVuZGVmaW5lZD4ge1xuICAgICAgICBpZiAoZmlsZU5hbWUgPT09IFJPVVRJTkdfRklMRSkge1xuICAgICAgICAgICAgbGV0IHJlc3VsdCA9IGF3YWl0IGdldFJvdXRpbmdGaWxlUmVzdWx0KHRoaXMuYWNjb3VudCwgdGhpcy5idWNrZXROYW1lKTtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQgJiYgeyB3cml0ZVRpbWU6IHJlc3VsdC53cml0ZVRpbWUsIHNpemU6IHJlc3VsdC5zaXplIH0gfHwgdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhd2FpdCAoYXdhaXQgdGhpcy5maW5kU3RvcmUoKSkuc3RvcmUuZ2V0SW5mbyh7IHBhdGg6IGZpbGVOYW1lLCAuLi5jb25maWcgfSk7XG4gICAgfVxuICAgIHB1YmxpYyBhc3luYyBmaW5kSW5mbyhwcmVmaXg6IHN0cmluZywgY29uZmlnPzogRmluZENvbmZpZyk6IFByb21pc2U8QXJjaGl2ZUZpbGVJbmZvW10+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IChhd2FpdCB0aGlzLmZpbmRTdG9yZSgpKS5zdG9yZS5maW5kSW5mbyh7IHByZWZpeCwgLi4uY29uZmlnIH0pO1xuICAgIH1cbiAgICBwdWJsaWMgYXN5bmMgZmluZChwcmVmaXg6IHN0cmluZywgY29uZmlnPzogRmluZENvbmZpZyk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICAgICAgcmV0dXJuIChhd2FpdCB0aGlzLmZpbmRJbmZvKHByZWZpeCwgY29uZmlnKSkubWFwKHggPT4geC5wYXRoKTtcbiAgICB9XG4gICAgcHVibGljIGFzeW5jIGdldFVSTChmaWxlUGF0aDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICAgICAgbGV0IHsgZG9tYWluLCBwb3J0IH0gPSBnZXRTdG9yYWdlU2VydmVyQ29uZmlnKCk7XG4gICAgICAgIHJldHVybiBidWlsZEZpbGVVcmwoYGh0dHBzOi8vJHtkb21haW59OiR7cG9ydH0vZmlsZS8ke2VuY29kZVVSSUNvbXBvbmVudCh0aGlzLmFjY291bnQpfS8ke2VuY29kZVVSSUNvbXBvbmVudCh0aGlzLmJ1Y2tldE5hbWUpfWAsIGZpbGVQYXRoKTtcbiAgICB9XG4gICAgcHVibGljIGFzeW5jIGdldENvbmZpZygpOiBQcm9taXNlPEFyY2hpdmVzQ29uZmlnPiB7XG4gICAgICAgIHJldHVybiBnZXRCdWNrZXRDb25maWcoYXdhaXQgcmVxdWlyZUJ1Y2tldCh0aGlzLmFjY291bnQsIHRoaXMuYnVja2V0TmFtZSkpO1xuICAgIH1cbiAgICBwdWJsaWMgYXN5bmMgaGFzV3JpdGVBY2Nlc3MoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBwdWJsaWMgYXN5bmMgZ2V0Q2hhbmdlc0FmdGVyMihjb25maWc6IENoYW5nZXNBZnRlckNvbmZpZyk6IFByb21pc2U8QXJjaGl2ZUZpbGVJbmZvW10+IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IChhd2FpdCB0aGlzLmZpbmRTdG9yZSgpKS5zdG9yZS5nZXRDaGFuZ2VzQWZ0ZXIyKGNvbmZpZyk7XG4gICAgfVxuICAgIHB1YmxpYyBhc3luYyBnZXRTeW5jU3RhdHVzKCk6IFByb21pc2U8QXJjaGl2ZXNTeW5jU3RhdHVzPiB7XG4gICAgICAgIHJldHVybiBhd2FpdCBidWNrZXRTeW5jU3RhdHVzKGF3YWl0IHJlcXVpcmVCdWNrZXQodGhpcy5hY2NvdW50LCB0aGlzLmJ1Y2tldE5hbWUpKTtcbiAgICB9XG59XG5cbmNvbnN0IGxvY2FsQXJjaGl2ZXMgPSBuZXcgTWFwPHN0cmluZywgSUFyY2hpdmVzPigpO1xuZXhwb3J0IGZ1bmN0aW9uIGdldExvY2FsQXJjaGl2ZXMoYWNjb3VudDogc3RyaW5nLCBidWNrZXROYW1lOiBzdHJpbmcsIHNvdXJjZUNvbmZpZzogU291cmNlQ29uZmlnKTogSUFyY2hpdmVzIHtcbiAgICBsZXQga2V5ID0gYCR7YWNjb3VudH0vJHtidWNrZXROYW1lfXwke3N0YWJsZVN0cmluZ2lmeShzb3VyY2VDb25maWcpfWA7XG4gICAgbGV0IGV4aXN0aW5nID0gbG9jYWxBcmNoaXZlcy5nZXQoa2V5KTtcbiAgICBpZiAoZXhpc3RpbmcpIHJldHVybiBleGlzdGluZztcbiAgICBsZXQgYXJjaGl2ZXMgPSBuZXcgQnVja2V0SUFyY2hpdmVzV3JhcHBlcihhY2NvdW50LCBidWNrZXROYW1lLCBzb3VyY2VDb25maWcpO1xuICAgIGxvY2FsQXJjaGl2ZXMuc2V0KGtleSwgYXJjaGl2ZXMpO1xuICAgIHJldHVybiBhcmNoaXZlcztcbn1cbiJdfQ==
|
|
953
|
-
/* _JS_SOURCE_HASH = "dab61171b71c11af9b36c3fccb800e54160c632a865dd3a41a96121cf6bf6b5c"; */
|
|
382
|
+
exports.debugClearAccountWriteStats = debugClearAccountWriteStats;
|
|
383
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmFnZVNlcnZlclN0YXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3RvcmFnZVNlcnZlclN0YXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUVBLDJDQUF3QztBQUl4QyxpREFBd0c7QUFDeEcsaURBQXNFO0FBQ3RFLDJEQUE4RDtBQUM5RCxpREFBNkU7QUFDN0UsNkNBQXFEO0FBQ3JELDZDQUFrSjtBQUNsSixxRUFBdUY7QUFDdkYsMkNBQXdFO0FBa0N4RSwwTUFBME07QUFDbk0sS0FBSyxVQUFVLGFBQWEsQ0FBQyxPQUFlLEVBQUUsVUFBa0I7SUFDbkUsSUFBSSxNQUFNLEdBQUcsTUFBTSxlQUFlLENBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ3hELElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUNWLE1BQU0sSUFBSSxLQUFLLENBQUMsVUFBVSxPQUFPLElBQUksVUFBVSwrREFBK0QsSUFBSSxDQUFDLFNBQVMsQ0FBQywyQkFBWSxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDaEssQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDO0FBQ2xCLENBQUM7QUFORCxzQ0FNQztBQUVELG1tQkFBbW1CO0FBQ25tQixTQUFnQixlQUFlLENBQUMsT0FBZSxFQUFFLFVBQWtCLEVBQUUsWUFBc0M7SUFDdkcsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ2hCLE1BQU0sSUFBSSxLQUFLLENBQUMsMERBQTBELE9BQU8sSUFBSSxVQUFVLDhEQUE4RCxDQUFDLENBQUM7SUFDbkssQ0FBQztJQUNELHVOQUF1TjtJQUN2TixLQUFLLGVBQWUsQ0FBQyxPQUFPLEVBQUUsVUFBVSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUSxFQUFFLEVBQUUsV0FBQyxPQUFBLE9BQU8sQ0FBQyxLQUFLLENBQUMsa0JBQWtCLE9BQU8sSUFBSSxVQUFVLFlBQVksTUFBQSxDQUFDLENBQUMsS0FBSyxtQ0FBSSxDQUFDLEVBQUUsQ0FBQyxDQUFBLEVBQUEsQ0FBQyxDQUFDO0lBQ2hKLE9BQU8sUUFBUSxDQUFDLE9BQU8sRUFBRSxVQUFVLEVBQUUsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQzVELENBQUM7QUFQRCwwQ0FPQztBQUVELCtRQUErUTtBQUN4USxLQUFLLFVBQVUsa0JBQWtCLENBQUMsT0FBZSxFQUFFLFVBQWtCLEVBQUUsTUFBNkY7SUFDdkssSUFBSSxNQUFNLEdBQUcsTUFBTSxhQUFhLENBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ3RELElBQUksT0FBTyxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxLQUFLLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxDQUFDLGlCQUFpQixFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMvSyxJQUFJLElBQW1FLENBQUM7SUFDeEUsS0FBSyxJQUFJLE1BQU0sSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUN6QixJQUFJLE1BQU0sSUFBSSxDQUFDLENBQUMsSUFBSSxJQUFJLE1BQU0sQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUM7WUFDekQsSUFBSSxHQUFHLE1BQU0sQ0FBQztRQUNsQixDQUFDO0lBQ0wsQ0FBQztJQUNELE9BQU8sSUFBSSxDQUFDO0FBQ2hCLENBQUM7QUFWRCxnREFVQztBQUVELFNBQWdCLGVBQWUsQ0FBQyxNQUFtQjtJQUMvQyxJQUFJLEtBQUssR0FBRyxFQUFFLFNBQVMsRUFBRSxDQUFDLEVBQUUsU0FBUyxFQUFFLENBQUMsRUFBRSxDQUFDO0lBQzNDLElBQUksWUFBWSxHQUFrRSxFQUFFLENBQUM7SUFDckYsSUFBSSxPQUFPLEdBQW1CLEVBQUUsQ0FBQztJQUNqQyxJQUFJLGVBQW1DLENBQUM7SUFDeEMsS0FBSyxJQUFJLENBQUMsSUFBSSxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDMUIsSUFBSSxRQUFRLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUN6QyxLQUFLLENBQUMsU0FBUyxJQUFJLFFBQVEsQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDO1FBQzVDLEtBQUssQ0FBQyxTQUFTLElBQUksUUFBUSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUM7UUFDNUMsWUFBWSxDQUFDLElBQUksQ0FBQyxHQUFHLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUN2QyxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2xDLGVBQWUsR0FBRyxlQUFlLElBQUksUUFBUSxDQUFDLGVBQWUsQ0FBQztJQUNsRSxDQUFDO0lBQ0QsT0FBTztRQUNILG1FQUFtRTtRQUNuRSxvQkFBb0IsRUFBRSxJQUFJO1FBQzFCLFlBQVksRUFBRSxNQUFNLENBQUMsT0FBTztRQUM1QixLQUFLO1FBQ0wsWUFBWTtRQUNaLGVBQWU7UUFDZixPQUFPO0tBQ1YsQ0FBQztBQUNOLENBQUM7QUF0QkQsMENBc0JDO0FBRU0sS0FBSyxVQUFVLGdCQUFnQixDQUFDLE1BQW1CO0lBQ3RELElBQUksUUFBUSxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsYUFBYSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ2xGLE9BQU87UUFDSCxnQkFBZ0IsRUFBRSxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDO1FBQ3pELFNBQVMsRUFBRSxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDO1FBQzVELE9BQU8sRUFBRSxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztLQUM1QyxDQUFDO0FBQ04sQ0FBQztBQVBELDRDQU9DO0FBRU0sS0FBSyxVQUFVLHNCQUFzQixDQUFDLE1BQW1CO0lBQzVELElBQUksTUFBTSxHQUFHLE1BQU0sT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsa0JBQWtCLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDckYsT0FBTztRQUNILFNBQVMsRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDO1FBQzFELFNBQVMsRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDO1FBQzFELE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztLQUMxQyxDQUFDO0FBQ04sQ0FBQztBQVBELHdEQU9DO0FBRUQsTUFBTSxPQUFPLEdBQUcsSUFBSSxHQUFHLEVBQTRDLENBQUM7QUFDcEUsc0dBQXNHO0FBQ3RHLE1BQU0sYUFBYSxHQUFHLElBQUksR0FBRyxFQUF1QixDQUFDO0FBRXJELG1PQUFtTztBQUNuTyxTQUFnQixlQUFlO0lBQzNCLE9BQU8sQ0FBQyxHQUFHLGFBQWEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDO0FBQ3ZDLENBQUM7QUFGRCwwQ0FFQztBQUVELE1BQU0sc0JBQXNCLEdBQUcsSUFBSSxHQUFHLEVBQXFCLENBQUM7QUFDNUQsOFZBQThWO0FBQzlWLFNBQWdCLHFCQUFxQixDQUFDLEdBQVc7SUFDN0MsSUFBSSxRQUFRLEdBQUcsc0JBQXNCLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQy9DLElBQUksUUFBUTtRQUFFLE9BQU8sUUFBUSxDQUFDO0lBQzlCLElBQUksWUFBc0MsQ0FBQztJQUMzQyxJQUFJLEdBQUcsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQztRQUM3QixxTkFBcU47UUFDck4sWUFBWSxHQUFHLElBQUEsOEJBQWUsRUFBQyxHQUFHLENBQUMsQ0FBQztJQUN4QyxDQUFDO0lBQ0QsSUFBSSxRQUFRLEdBQUcsSUFBQSxnQ0FBaUIsRUFBQyxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUNoRSxzQkFBc0IsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQzFDLE9BQU8sUUFBUSxDQUFDO0FBQ3BCLENBQUM7QUFYRCxzREFXQztBQUVELHVXQUF1VztBQUN2VyxTQUFTLG1CQUFtQixDQUFDLFlBQXNDLEVBQUUsTUFBYztJQUMvRSxJQUFJLENBQUMsWUFBWTtRQUFFLE9BQU8sTUFBTSxDQUFDO0lBQ2pDLE9BQU8sWUFBWSxDQUFDLFlBQVksSUFBSSxZQUFZLENBQUMsR0FBRyxDQUFDO0FBQ3pELENBQUM7QUFFRCxrTkFBa047QUFDbE47Ozs7R0FJRztBQUNILE1BQU0sTUFBTSxHQUFHLElBQUksR0FBRyxFQUFxQixDQUFDO0FBRTVDLFNBQWdCLFFBQVEsQ0FBQyxPQUFlLEVBQUUsVUFBa0IsRUFBRSxJQUFZO0lBQ3RFLDhHQUE4RztJQUM5RyxJQUFBLGtDQUFxQixFQUFDLElBQUksQ0FBQyxDQUFDO0lBQzVCLElBQUksTUFBTSxHQUFHLElBQUEsNEJBQWUsRUFBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ3hELElBQUksUUFBUSxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDbEMsSUFBSSxRQUFRO1FBQUUsT0FBTyxRQUFRLENBQUM7SUFDOUIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsY0FBYyxPQUFPLElBQUksVUFBVSxZQUFZLE1BQU0sbURBQW1ELENBQUMsQ0FBQztJQUMzSixJQUFJLEtBQUssR0FBRyxJQUFJLHFCQUFTLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRTtRQUNwQyxtRUFBbUU7UUFDbkUsTUFBTSxFQUFFLE1BQU0sQ0FBQyxFQUFFLENBQUMsSUFBQSx3QkFBWSxFQUFDLE1BQU0sRUFBRSxPQUFPLEVBQUUsVUFBVSxDQUFDO1FBQzNELFlBQVksRUFBRSxNQUFNLENBQUMsRUFBRSxDQUFDLElBQUEsZ0NBQWlCLEVBQUMsRUFBRSxZQUFZLEVBQUUsTUFBTSxDQUFDLFlBQVksRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUN2SCxXQUFXLEVBQUUsQ0FBQyxNQUFNLEVBQUUsWUFBWSxFQUFFLFVBQVUsRUFBRSxFQUFFLENBQUMsSUFBQSxnQ0FBaUIsRUFBQyxNQUFNLEVBQUUsWUFBWSxFQUFFLFVBQVUsQ0FBQztRQUN0RyxjQUFjLEVBQUUsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLE9BQU8sSUFBSSxVQUFVLEVBQUUsRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDO1FBQzFGLGdCQUFnQixFQUFFLHFCQUFxQjtLQUMxQyxDQUFDLENBQUM7SUFDSCxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQztJQUMxQixrS0FBa0s7SUFDbEssS0FBSyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBUSxFQUFFLEVBQUUsV0FBQyxPQUFBLE9BQU8sQ0FBQyxLQUFLLENBQUMsc0JBQXNCLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLGNBQWMsT0FBTyxJQUFJLFVBQVUsWUFBWSxNQUFBLENBQUMsQ0FBQyxLQUFLLG1DQUFJLENBQUMsRUFBRSxDQUFDLENBQUEsRUFBQSxDQUFDLENBQUM7SUFDOUosT0FBTyxLQUFLLENBQUM7QUFDakIsQ0FBQztBQW5CRCw0QkFtQkM7QUFFRCx5UUFBeVE7QUFDelEsU0FBUyxXQUFXLENBQUMsT0FBZSxFQUFFLFVBQWtCLEVBQUUsS0FBZSxFQUFFLE9BQWlDO0lBQ3hHLElBQUksSUFBSSxHQUFHLE9BQU8sSUFBSSxJQUFBLDBCQUFjLEVBQUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxPQUFPLENBQUMsSUFBSSxTQUFTLENBQUM7SUFDaEYsSUFBSSxhQUFhLEdBQUcsSUFBSSxHQUFHLEVBQTBCLENBQUM7SUFDdEQsS0FBSyxJQUFJLFNBQVMsSUFBSSxDQUFBLElBQUksYUFBSixJQUFJLHVCQUFKLElBQUksQ0FBRSxNQUFNLEtBQUksRUFBRSxFQUFFLENBQUM7UUFDdkMsYUFBYSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsSUFBSSxFQUFFLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN6RCxDQUFDO0lBQ0QsMklBQTJJO0lBQzNJLElBQUksTUFBTSxHQUFrQixLQUFLLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUMzQyxJQUFJO1FBQ0osT0FBTyxFQUFFLGFBQWEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRTtRQUN0QyxNQUFNLEVBQUUsSUFBQSw0QkFBZSxFQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsVUFBVSxDQUFDO1FBQ2xELEtBQUssRUFBRSxRQUFRLENBQUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxJQUFJLENBQUM7S0FDN0MsQ0FBQyxDQUFDLENBQUM7SUFDSixJQUFJLE1BQU0sR0FBZ0IsRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBRSxXQUFXLEVBQUUsQ0FBQSxJQUFJLGFBQUosSUFBSSx1QkFBSixJQUFJLENBQUUsV0FBVyxLQUFJLEVBQUUsRUFBRSxJQUFJLEVBQUUsSUFBSSxhQUFKLElBQUksdUJBQUosSUFBSSxDQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQztJQUMzSCxhQUFhLENBQUMsR0FBRyxDQUFDLEdBQUcsT0FBTyxJQUFJLFVBQVUsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ3RELElBQUEsNkNBQW9CLEVBQUMsTUFBTSxDQUFDLENBQUM7SUFDN0IsT0FBTyxNQUFNLENBQUM7QUFDbEIsQ0FBQztBQUVELG1QQUFtUDtBQUNuUCxLQUFLLFVBQVUsVUFBVSxDQUFDLE9BQWUsRUFBRSxVQUFrQjtJQUN6RCxJQUFJLE9BQU8sR0FBRyxNQUFNLElBQUEsbUNBQXNCLEVBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ2hFLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTTtRQUFFLE9BQU8sU0FBUyxDQUFDO0lBQ3RDLElBQUksT0FBTyxHQUFHLE1BQU0sSUFBQSxnQ0FBbUIsRUFBQyxPQUFPLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFDN0QsT0FBTyxXQUFXLENBQUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBQy9FLENBQUM7QUFFRCxTQUFnQixlQUFlLENBQUMsT0FBZSxFQUFFLFVBQWtCO0lBQy9ELElBQUksR0FBRyxHQUFHLEdBQUcsT0FBTyxJQUFJLFVBQVUsRUFBRSxDQUFDO0lBQ3JDLE9BQU8sT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxZQUFZLENBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0FBQ2pFLENBQUM7QUFIRCwwQ0FHQztBQUVELG9YQUFvWDtBQUM3VyxLQUFLLFVBQVUsWUFBWSxDQUFDLE9BQWUsRUFBRSxVQUFrQjtJQUNsRSxJQUFJLEdBQUcsR0FBRyxHQUFHLE9BQU8sSUFBSSxVQUFVLEVBQUUsQ0FBQztJQUNyQyxJQUFJLE1BQU0sR0FBRyxVQUFVLENBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQzdDLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ3pCLEtBQUssTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRTtRQUN0QixJQUFJLENBQUMsTUFBTSxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEtBQUssTUFBTSxFQUFFLENBQUM7WUFDekMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN4QixDQUFDO0lBQ0wsQ0FBQyxFQUFFLEdBQUcsRUFBRTtRQUNKLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsS0FBSyxNQUFNLEVBQUUsQ0FBQztZQUM5QixPQUFPLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3hCLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztJQUNILE9BQU8sTUFBTSxNQUFNLENBQUM7QUFDeEIsQ0FBQztBQWRELG9DQWNDO0FBRUQ7Ozs7Ozs7O0dBUUc7QUFDSSxLQUFLLFVBQVUsa0JBQWtCLENBQUMsT0FBZSxFQUFFLFVBQWtCLEVBQUUsSUFBWSxFQUFFLElBQVksRUFBRSxNQUFrQzs7SUFDeEksSUFBQSxrQ0FBbUIsR0FBRSxDQUFDO0lBQ3RCLElBQUksS0FBSyxHQUFHLFFBQVEsQ0FBQyxPQUFPLEVBQUUsVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ2hELElBQUksUUFBUSxHQUFHLElBQUEsK0JBQWdCLEVBQUMsSUFBSSxDQUFDLENBQUM7SUFDdEMsSUFBSSxPQUFPLEdBQUcsTUFBQSxDQUFDLE1BQU0sZUFBZSxDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUMsQ0FBQywwQ0FBRSxPQUFPLENBQUM7SUFDcEUsSUFBSSxNQUFNLEdBQUcsSUFBQSw4Q0FBcUIsRUFBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDdEQsTUFBTSxLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUUsSUFBSSxFQUFFLDJCQUFZLEVBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBQSxvQ0FBcUIsRUFBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLFlBQVksRUFBRSxNQUFNLGFBQU4sTUFBTSx1QkFBTixNQUFNLENBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQztJQUM5SCxnTkFBZ047SUFDaE4sTUFBTSxZQUFZLENBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ3hDLElBQUEsMkNBQXVCLEdBQUUsQ0FBQztBQUM5QixDQUFDO0FBVkQsZ0RBVUM7QUFFRCx3S0FBd0s7QUFDeEssU0FBZ0IsbUJBQW1CO0lBQy9CLE9BQU8sQ0FBQyxHQUFHLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRTtRQUNqQyxJQUFJLEtBQUssR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzdCLE9BQU8sRUFBRSxPQUFPLEVBQUUsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLEVBQUUsVUFBVSxFQUFFLEdBQUcsQ0FBQyxLQUFLLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDOUUsQ0FBQyxDQUFDLENBQUM7QUFDUCxDQUFDO0FBTEQsa0RBS0M7QUF5QkQsU0FBUyxrQkFBa0IsQ0FBQyxNQUFtQjs7SUFDM0MsT0FBTztRQUNILGdHQUFnRztRQUNoRyxNQUFNLEVBQUUsQ0FBQSxNQUFBLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLDBDQUFFLE1BQU0sS0FBSSxFQUFFO1FBQ3RDLE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTztRQUN2QixXQUFXLEVBQUUsTUFBTSxDQUFDLFdBQVc7UUFDL0IsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJO1FBQ2pCLE1BQU0sRUFBRSxlQUFlLENBQUMsTUFBTSxDQUFDO0tBQ2xDLENBQUM7QUFDTixDQUFDO0FBRUQsa1JBQWtSO0FBQzNRLEtBQUssVUFBVSxvQkFBb0IsQ0FBQyxPQUFlLEVBQUUsVUFBa0I7O0lBQzFFLElBQUksR0FBRyxHQUFHLEdBQUcsT0FBTyxJQUFJLFVBQVUsRUFBRSxDQUFDO0lBQ3JDLElBQUksYUFBYSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDckMsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ2pCLE9BQU8sVUFBVSxHQUFHLG1GQUFtRixDQUFDO0lBQzVHLENBQUM7SUFDRCxJQUFJLE1BQStCLENBQUM7SUFDcEMsSUFBSSxDQUFDO1FBQ0QsTUFBTSxHQUFHLE1BQU0sYUFBYSxDQUFDO0lBQ2pDLENBQUM7SUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ1QsT0FBTyxVQUFVLEdBQUcsbUNBQW1DLE1BQU0sQ0FBQyxNQUFDLENBQVcsQ0FBQyxLQUFLLG1DQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQztJQUMzRyxDQUFDO0lBQ0QsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ1YsT0FBTyxVQUFVLEdBQUcsZ0NBQWdDLENBQUM7SUFDekQsQ0FBQztJQUNELE9BQU8sa0JBQWtCLENBQUMsTUFBTSxDQUFDLENBQUM7QUFDdEMsQ0FBQztBQWhCRCxvREFnQkM7QUFFRCxzV0FBc1c7QUFDL1YsS0FBSyxVQUFVLGNBQWMsQ0FBQyxPQUFlLEVBQUUsVUFBa0I7O0lBQ3BFLElBQUksR0FBRyxHQUFHLEdBQUcsT0FBTyxJQUFJLFVBQVUsRUFBRSxDQUFDO0lBQ3JDLElBQUksU0FBUyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDakMsSUFBSSxNQUErQixDQUFDO0lBQ3BDLElBQUksQ0FBQztRQUNELE1BQU0sR0FBRyxNQUFNLGVBQWUsQ0FBQyxPQUFPLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFDeEQsQ0FBQztJQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7UUFDVCxPQUFPLFVBQVUsR0FBRyxtQ0FBbUMsTUFBTSxDQUFDLE1BQUMsQ0FBVyxDQUFDLEtBQUssbUNBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDO0lBQzNHLENBQUM7SUFDRCxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDVixPQUFPLFVBQVUsR0FBRyxpRUFBaUUsSUFBQSw0QkFBZSxFQUFDLFFBQVEsRUFBRSxPQUFPLEVBQUUsVUFBVSxDQUFDLEdBQUcsQ0FBQztJQUMzSSxDQUFDO0lBQ0QsOExBQThMO0lBQzlMLEtBQUssSUFBSSxDQUFDLElBQUksTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQzFCLE1BQU0sQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUN6QixDQUFDO0lBQ0QsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ2IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxvQkFBb0IsR0FBRyxpREFBaUQsQ0FBQyxDQUFDO0lBQzFGLENBQUM7SUFDRCxPQUFPLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQ3RDLENBQUM7QUFwQkQsd0NBb0JDO0FBRU0sS0FBSyxVQUFVLHVCQUF1QixDQUFDLE9BQWU7SUFDekQsSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQ3ZCLElBQUksT0FBTyxHQUFHLElBQUksR0FBRyxFQUFrQixDQUFDO0lBQ3hDLEtBQUssVUFBVSxLQUFLLENBQUksSUFBWSxFQUFFLEdBQXFCO1FBQ3ZELElBQUksS0FBSyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUN2QixJQUFJLENBQUM7WUFDRCxPQUFPLE1BQU0sR0FBRyxFQUFFLENBQUM7UUFDdkIsQ0FBQztnQkFBUyxDQUFDO1lBQ1AsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFDdkUsQ0FBQztJQUNMLENBQUM7SUFDRCw0SUFBNEk7SUFDNUksSUFBSSxPQUFPLEdBQUcsTUFBTSxLQUFLLENBQUMsU0FBUyxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUEsb0NBQXVCLEVBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUM3RSxJQUFJLFFBQVEsR0FBRyxJQUFJLEdBQUcsRUFBa0IsQ0FBQztJQUN6QyxLQUFLLElBQUksS0FBSyxJQUFJLE9BQU8sRUFBRSxDQUFDO1FBQ3hCLElBQUksUUFBUSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDO1lBQUUsU0FBUztRQUM3QyxRQUFRLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ2pELENBQUM7SUFDRCxJQUFJLEtBQUssR0FBRyxDQUFDLEdBQUcsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7SUFDakMsSUFBSSxDQUFDO1FBQ0QsT0FBTyxNQUFNLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUMsVUFBVSxFQUFDLEVBQUU7O1lBQ2xELElBQUksR0FBRyxHQUFHLEdBQUcsT0FBTyxJQUFJLFVBQVUsRUFBRSxDQUFDO1lBQ3JDLElBQUksTUFBTSxHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQzVDLElBQUksSUFBSSxHQUFxQixFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxDQUFDO1lBQ25FLElBQUksQ0FBQyxJQUFJLEdBQUcsTUFBTSxLQUFLLENBQUMsUUFBUSxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUEsd0JBQVcsRUFBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQVEsRUFBRSxFQUFFOztnQkFDNUUsSUFBSSxDQUFDLFNBQVMsR0FBRyxNQUFNLENBQUMsTUFBQSxDQUFDLENBQUMsS0FBSyxtQ0FBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO2dCQUNwRCxPQUFPLFNBQVMsQ0FBQztZQUNyQixDQUFDLENBQUMsQ0FBQztZQUNILElBQUksQ0FBQyxVQUFVLEdBQUcsbUJBQW1CLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDM0MsTUFBTSxhQUFhLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUN2QyxJQUFJLGFBQWEsRUFBRSxDQUFDO2dCQUNoQixJQUFJLENBQUM7b0JBQ0QsSUFBSSxNQUFNLEdBQUcsTUFBTSxLQUFLLENBQUMsYUFBYSxFQUFFLEdBQUcsRUFBRSxDQUFDLGFBQWEsQ0FBQyxDQUFDO29CQUM3RCxJQUFJLE1BQU0sRUFBRSxDQUFDO3dCQUNULE9BQU8sRUFBRSxHQUFHLElBQUksRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxlQUFlLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztvQkFDdEUsQ0FBQztnQkFDTCxDQUFDO2dCQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7b0JBQ1QsT0FBTyxFQUFFLEdBQUcsSUFBSSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxNQUFDLENBQVcsQ0FBQyxLQUFLLG1DQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDM0YsQ0FBQztZQUNMLENBQUM7WUFDRCxJQUFJLENBQUM7Z0JBQ0QsTUFBTSxNQUFNLEdBQUcsTUFBTSxLQUFLLENBQUMsaUJBQWlCLEVBQUUsR0FBRyxFQUFFLENBQUMsSUFBQSxnQ0FBbUIsRUFBQyxPQUFPLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQztnQkFDOUYsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO29CQUNWLE9BQU8sRUFBRSxHQUFHLElBQUksRUFBRSxLQUFLLEVBQUUsb0JBQW9CLDJCQUFZLHdCQUF3QixFQUFFLENBQUM7Z0JBQ3hGLENBQUM7Z0JBQ0QsT0FBTyxFQUFFLEdBQUcsSUFBSSxFQUFFLE1BQU0sRUFBRSxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsRUFBRSxDQUFDO1lBQ3pELENBQUM7WUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO2dCQUNULE9BQU8sRUFBRSxHQUFHLElBQUksRUFBRSxLQUFLLEVBQUUsTUFBTSxDQUFDLE1BQUMsQ0FBVyxDQUFDLEtBQUssbUNBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQzdFLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ1IsQ0FBQztZQUFTLENBQUM7UUFDUCxvR0FBb0c7UUFDcEcsSUFBSSxLQUFLLEdBQUcsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLElBQUksSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUMzRSxPQUFPLENBQUMsR0FBRyxDQUFDLDJCQUEyQixPQUFPLFVBQVUsSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLEtBQUssVUFBVSxLQUFLLENBQUMsTUFBTSxhQUFhLEtBQUssRUFBRSxDQUFDLENBQUM7SUFDMUgsQ0FBQztBQUNMLENBQUM7QUF2REQsMERBdURDO0FBVUQsU0FBUyxlQUFlO0lBQ3BCLE9BQU8sRUFBRSxjQUFjLEVBQUUsQ0FBQyxFQUFFLGFBQWEsRUFBRSxDQUFDLEVBQUUsYUFBYSxFQUFFLENBQUMsRUFBRSxZQUFZLEVBQUUsQ0FBQyxFQUFFLENBQUM7QUFDdEYsQ0FBQztBQUVELDJKQUEySjtBQUMzSixNQUFNLFVBQVUsR0FBRyxJQUFJLEdBQUcsRUFBNEIsQ0FBQztBQUV2RCxTQUFTLGdCQUFnQixDQUFDLEdBQVcsRUFBRSxJQUE0QixFQUFFLEtBQWE7SUFDOUUsSUFBSSxLQUFLLEdBQUcsVUFBVSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNoQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDVCxLQUFLLEdBQUcsZUFBZSxFQUFFLENBQUM7UUFDMUIsVUFBVSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDL0IsQ0FBQztJQUNELElBQUksSUFBSSxLQUFLLFVBQVUsRUFBRSxDQUFDO1FBQ3RCLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUN2QixLQUFLLENBQUMsYUFBYSxJQUFJLEtBQUssQ0FBQztJQUNqQyxDQUFDO1NBQU0sQ0FBQztRQUNKLEtBQUssQ0FBQyxhQUFhLEVBQUUsQ0FBQztRQUN0QixLQUFLLENBQUMsWUFBWSxJQUFJLEtBQUssQ0FBQztJQUNoQyxDQUFDO0FBQ0wsQ0FBQztBQUVELFNBQVMsbUJBQW1CLENBQUMsR0FBVztJQUNwQyxPQUFPLFVBQVUsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksZUFBZSxFQUFFLENBQUM7QUFDcEQsQ0FBQztBQUVELGtFQUFrRTtBQUNsRSxTQUFnQiwyQkFBMkIsQ0FBQyxPQUFlO0lBQ3ZELElBQUksTUFBTSxHQUFHLEdBQUcsT0FBTyxHQUFHLENBQUM7SUFDM0IsSUFBSSxPQUFPLEdBQUcsQ0FBQyxDQUFDO0lBQ2hCLEtBQUssSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLFVBQVUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxFQUFFLENBQUM7UUFDckMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDO1lBQUUsU0FBUztRQUN0QyxVQUFVLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ3ZCLE9BQU8sRUFBRSxDQUFDO0lBQ2QsQ0FBQztJQUNELE9BQU8sQ0FBQyxHQUFHLENBQUMsbUNBQW1DLE9BQU8sdUJBQXVCLE9BQU8sRUFBRSxDQUFDLENBQUM7SUFDeEYsT0FBTyxPQUFPLENBQUM7QUFDbkIsQ0FBQztBQVZELGtFQVVDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHBhdGggZnJvbSBcInBhdGhcIjtcbmltcG9ydCBmcyBmcm9tIFwiZnNcIjtcbmltcG9ydCB7IEJsb2JTdG9yZSB9IGZyb20gXCIuL2Jsb2JTdG9yZVwiO1xuaW1wb3J0IHtcbiAgICBSZW1vdGVDb25maWcsIEhvc3RlZENvbmZpZywgU291cmNlQ29uZmlnLCBJQXJjaGl2ZXMsIEFyY2hpdmVzQ29uZmlnLCBBcmNoaXZlc1N5bmNTdGF0dXMsIFN5bmNBY3Rpdml0eSxcbn0gZnJvbSBcIi4uL0lBcmNoaXZlc1wiO1xuaW1wb3J0IHsgUk9VVElOR19GSUxFLCBwYXJzZVJvdXRpbmdEYXRhLCBzZXJpYWxpemVSZW1vdGVDb25maWcsIG5vcm1hbGl6ZVNvdXJjZSB9IGZyb20gXCIuL3JlbW90ZUNvbmZpZ1wiO1xuaW1wb3J0IHsgY3JlYXRlU3RvcmVTb3VyY2UsIGFwcGx5U291cmNlQ29uZmlnIH0gZnJvbSBcIi4vc3RvcmVTb3VyY2VzXCI7XG5pbXBvcnQgeyBicm9hZGNhc3RSb3V0aW5nQ2hhbmdlZCB9IGZyb20gXCIuL3N0b3JhZ2VDb250cm9sbGVyXCI7XG5pbXBvcnQgeyBnZXRTdG9yYWdlU2VydmVyQ29uZmlnLCBhc3NlcnRXcml0ZXNBbGxvd2VkIH0gZnJvbSBcIi4vc2VydmVyQ29uZmlnXCI7XG5pbXBvcnQgeyBhc3NlcnRWYWxpZFNvdXJjZU5hbWUgfSBmcm9tIFwiLi92YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBnZXRCdWNrZXRGb2xkZXIsIGxpc3RBY2NvdW50U3RvcmVGb2xkZXJzLCBsaXN0QnVja2V0U3RvcmVGb2xkZXJzLCByZWFkUm91dGluZ0Zyb21EaXNrLCBnZXREaXNrSW5mbywgQnVja2V0RGlza0luZm8gfSBmcm9tIFwiLi9idWNrZXREaXNrXCI7XG5pbXBvcnQgeyBzY2hlZHVsZUJvdW5kYXJ5V29yaywgcmVpbmplY3RJbnRlcm1lZGlhdGVzIH0gZnJvbSBcIi4vaW50ZXJtZWRpYXRlTWFuYWdlbWVudFwiO1xuaW1wb3J0IHsgcGxhblNlbGZTdG9yZXMsIGlzU2VsZlNvdXJjZSwgU2VsZlN1bW1hcnkgfSBmcm9tIFwiLi9zdG9yZVBsYW5cIjtcblxuLyoqXG4gKiBXaGF0IHRoaXMgc2VydmVyIEhBUywgYXMgb3Bwb3NlZCB0byB3aGF0IGFueSBvZiBpdCBkb2VzLiBGb3VyIHRoaW5ncywgYW5kIG5vdGhpbmcgZWxzZTpcbiAqXG4gKiAtIHRoZSBzdG9yZXMsIGJ5IGZvbGRlciAoZ2V0U3RvcmUpIC0gbWFkZSBvbmNlLCBhbmQgc2VsZi1jb25maWd1cmluZyBmcm9tIHRoZXJlXG4gKiAtIHdoaWNoIG9mIHRoZW0gYSByZXF1ZXN0IG1lYW5zIChmaW5kQnVja2V0U3RvcmUpLCB3aGljaCBpcyBvbmx5IGV2ZXIgYSBuYW1lXG4gKiAtIHdoYXQgZXhpc3RzIG9uIGRpc2ssIGZvciBsaXN0aW5ncyBhbmQgZm9yIHRoZSBwYWdlcyB0aGF0IHJlcG9ydCBpdFxuICpcbiAqIEl0IGRlY2lkZXMgbm90aGluZyBhYm91dCByb3V0ZXMsIHdpbmRvd3Mgb3IgcGVlcnMgLSBhIHN0b3JlIHJlYWRzIGl0cyBvd24gY29uZmlnIGFuZCB3b3JrcyB0aGF0XG4gKiBvdXQgaXRzZWxmIChCbG9iU3RvcmUuYXBwbHlSb3V0aW5nQ29uZmlnKSAtIGFuZCBpdCBzY2hlZHVsZXMgbm90aGluZzogc3dpdGNob3ZlcnMgYW5kIHRoZSBoYW5kb3ZlcnNcbiAqIHRoZXkgY2F1c2UgbGl2ZSBpbiBpbnRlcm1lZGlhdGVNYW5hZ2VtZW50LlxuICovXG5cbmV4cG9ydCB0eXBlIExvYWRlZFN0b3JlID0ge1xuICAgIC8vIFRoZSBuYW1lIGl0cyBlbnRyaWVzIGdhdmUgaXQgKHNlZSBDb21tb25Db25maWcubmFtZSkgLSBpdHMgaWRlbnRpdHkgaGVyZSwgaXRzIGZvbGRlciBvbiBkaXNrLCBhbmQgaG93IGEgcmVxdWVzdCBmaW5kcyBpdFxuICAgIG5hbWU6IHN0cmluZztcbiAgICAvLyBUaGUgZXhhY3Qgc2VsZiBlbnRyaWVzIHRoaXMgc3RvcmUgc2VydmVzIChzYW1lIHJvdXRlLCBkaWZmZXJlbnQgdmFsaWQgd2luZG93cykuIEVtcHR5IHdoZW4gd2UgYXJlIG5vdCBpbiB0aGUgY29uZmlnIGJ1dCBzdGlsbCBzZXJ2ZSBvdXIgZGlzayBkYXRhLlxuICAgIGVudHJpZXM6IEhvc3RlZENvbmZpZ1tdO1xuICAgIGZvbGRlcjogc3RyaW5nO1xuICAgIHN0b3JlOiBCbG9iU3RvcmU7XG59O1xuXG4vLyBBIGJ1Y2tldCBsb2FkZWQgb24gdGhpcyBzZXJ2ZXI6IHRoZSBzdG9yZXMgaXQgaGFzIGhlcmUsIGFuZCB3aGF0IHRoZSBuZXdlc3Qgb2YgdGhlaXIgY29uZmlncyBzYXlzIGFib3V0IHVzLiBQdXJlIGRhdGEgLSB0aGUgc3RvcmVzIHRoZW1zZWx2ZXMgZG8gdGhlIHdvcmssIGluY2x1ZGluZyBjb25maWd1cmluZyB0aGVtc2VsdmVzLlxuZXhwb3J0IHR5cGUgQnVja2V0U3RhdGUgPSB7XG4gICAgYWNjb3VudDogc3RyaW5nO1xuICAgIGJ1Y2tldE5hbWU6IHN0cmluZztcbiAgICAvLyBUaGUgbmV3ZXN0IHJvdXRpbmcgY29uZmlnIGFtb25nIGl0cyBzdG9yZXMsIG9yIGFic2VudCB3aGVuIG5vbmUgb2YgdGhlbSBoYXMgb25lIHlldFxuICAgIHJvdXRpbmc/OiBSZW1vdGVDb25maWc7XG4gICAgc2VsZkVudHJpZXM6IEhvc3RlZENvbmZpZ1tdO1xuICAgIHNlbGY6IFNlbGZTdW1tYXJ5IHwgdW5kZWZpbmVkO1xuICAgIHN0b3JlczogTG9hZGVkU3RvcmVbXTtcbn07XG5cbi8qKiBUaGUgbG9hZGVkIGJ1Y2tldCwgbG9hZGluZyBpdCAod2hpY2ggaW5zdGFudGlhdGVzIGl0cyBzdG9yZXMgYW5kIHN0YXJ0cyB0aGVpciBzeW5jaHJvbml6YXRpb24pIGlmIG5lZWRlZC4gQSBidWNrZXQgdGhhdCBkb2VzIG5vdCBleGlzdCBvbiB0aGlzIHNlcnZlciB0aHJvd3MgLSBjYWxsZXJzIG5ldmVyIHNlZSB1bmRlZmluZWQgYnVja2V0cy4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXF1aXJlQnVja2V0KGFjY291bnQ6IHN0cmluZywgYnVja2V0TmFtZTogc3RyaW5nKTogUHJvbWlzZTxCdWNrZXRTdGF0ZT4ge1xuICAgIGxldCBidWNrZXQgPSBhd2FpdCBnZXRMb2FkZWRCdWNrZXQoYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgaWYgKCFidWNrZXQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBCdWNrZXQgJHthY2NvdW50fS8ke2J1Y2tldE5hbWV9IGRvZXMgbm90IGV4aXN0IG9uIHRoaXMgc2VydmVyLiBXcml0ZSBpdHMgcm91dGluZyBjb25maWcgdG8gJHtKU09OLnN0cmluZ2lmeShST1VUSU5HX0ZJTEUpfSB0byBjcmVhdGUgaXQuYCk7XG4gICAgfVxuICAgIHJldHVybiBidWNrZXQ7XG59XG5cbi8qKiBUaGUgc3RvcmUgc2VydmluZyBhIHJlcXVlc3Q6IHRoZSBvbmUgdGhlIGNsaWVudCdzIHNlbGVjdGVkIGVudHJ5IE5BTUVTLiBBY2NvdW50LCBuYW1lLCBhbmQgYnVja2V0IEFSRSB0aGUgZm9sZGVyLCBzbyB0aGlzIGlzIGEgZGlyZWN0IGxvb2t1cCwgbmV2ZXIgYSBzZWFyY2ggb2Ygd2hhdCBleGlzdHMgLSBhbmQgYSBuYW1lIHRoaXMgc2VydmVyIGhhcyBuZXZlciBzZWVuIGlzIENSRUFURUQsIG5ldmVyIHJlamVjdGVkLCBiZWNhdXNlIGFza2luZyBmb3IgYSBuYW1lIGlzIHRoZSBpbnN0cnVjdGlvbiB0byBoYXZlIHRoYXQgc3RvcmUgKG9uZSBuYW1lLCBvbmUgZm9sZGVyLCBvbmUgaW5kZXg7IGl0IGNvbmZpZ3VyZXMgaXRzZWxmIG9uY2UgdGhlIHJvdXRpbmcgY29uZmlnIGxhbmRzIGluIGl0KS4gTm90aGluZyBlbHNlIGFib3V0IHRoZSByZXF1ZXN0IGlzIGNvbXBhcmVkIC0gbm90IHRoZSB3aW5kb3csIG5vdCB0aGUgcm91dGUsIG5vdCB0aGUgZmxhZ3MgLSB3aGljaCBpcyB0aGUgd2hvbGUgcG9pbnQgb2YgbmFtaW5nIGl0OiBhIGNsaWVudCBhIGNvbmZpZyB2ZXJzaW9uIGJlaGluZCBvbiBzb21lIGZsYWcgc3RpbGwgcmVhY2hlcyB0aGUgcmlnaHQgc3RvcmUuICovXG5leHBvcnQgZnVuY3Rpb24gZmluZEJ1Y2tldFN0b3JlKGFjY291bnQ6IHN0cmluZywgYnVja2V0TmFtZTogc3RyaW5nLCBzb3VyY2VDb25maWc6IFNvdXJjZUNvbmZpZyB8IHVuZGVmaW5lZCk6IEJsb2JTdG9yZSB7XG4gICAgaWYgKCFzb3VyY2VDb25maWcpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBObyByZW1vdGUgc291cmNlIGNvbmZpZ3VyYXRpb24gd2FzIHByb3ZpZGVkIGZvciBidWNrZXQgJHthY2NvdW50fS8ke2J1Y2tldE5hbWV9OiBldmVyeSByZXF1ZXN0IG11c3Qgc2F5IHdoaWNoIGNvbmZpZ3VyZWQgc291cmNlIGl0IHNlbGVjdGVkYCk7XG4gICAgfVxuICAgIC8vIE5vdCBwYXJ0IG9mIHJlc29sdmluZyB0aGUgcmVxdWVzdCAodGhlIG5hbWUgYWxyZWFkeSBzYXlzIGV2ZXJ5dGhpbmcpOiBsb2FkaW5nIHRoZSBidWNrZXQgaXMgd2hhdCBzY2hlZHVsZXMgaXRzIHN3aXRjaG92ZXIgd29yayBhbmQgbWFya3MgaXQgYWN0aXZlIGZvciBkZXBsb3kgaGFuZG9mZnMsIGFuZCBhIGJ1Y2tldCBzZXJ2aW5nIHJlcXVlc3RzIG11c3QgYmUgbG9hZGVkXG4gICAgdm9pZCBnZXRMb2FkZWRCdWNrZXQoYWNjb3VudCwgYnVja2V0TmFtZSkuY2F0Y2goKGU6IEVycm9yKSA9PiBjb25zb2xlLmVycm9yKGBMb2FkaW5nIGJ1Y2tldCAke2FjY291bnR9LyR7YnVja2V0TmFtZX0gZmFpbGVkOiAke2Uuc3RhY2sgPz8gZX1gKSk7XG4gICAgcmV0dXJuIGdldFN0b3JlKGFjY291bnQsIGJ1Y2tldE5hbWUsIHNvdXJjZUNvbmZpZy5uYW1lKTtcbn1cblxuLyoqIEludGVybmFsIChzdG9yZS10by1zdG9yZSkgcmVhZHMgc2tpcCBzdG9yZSBzZWxlY3Rpb24gZW50aXJlbHk6IHRoZSBjYWxsZXIgaXMgYW5vdGhlciBzdG9yZSB3aG9zZSBpbmRleCBzYXlzIHRoaXMgTUFDSElORSBob2xkcyB0aGUgYnl0ZXMgLSB0aGUgcGVyc2lzdGVkIGhvbGRlciBpZGVudGl0eSBpcyBqdXN0IGEgVVJMLCB3aGljaCBjYW5ub3QgbmFtZSBhIHN0b3JlLiBXaGljaGV2ZXIgc3RvcmUncyBmb2xkZXIgaGFzIHRoZSBuZXdlc3QgY29weSBhbnN3ZXJzLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWRCdWNrZXRJbnRlcm5hbChhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZywgY29uZmlnOiB7IHBhdGg6IHN0cmluZzsgcmFuZ2U/OiB7IHN0YXJ0OiBudW1iZXI7IGVuZDogbnVtYmVyIH07IGluY2x1ZGVUb21ic3RvbmVzPzogYm9vbGVhbiB9KTogUHJvbWlzZTx7IGRhdGE6IEJ1ZmZlcjsgd3JpdGVUaW1lOiBudW1iZXI7IHNpemU6IG51bWJlciB9IHwgdW5kZWZpbmVkPiB7XG4gICAgbGV0IGJ1Y2tldCA9IGF3YWl0IHJlcXVpcmVCdWNrZXQoYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgbGV0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbChidWNrZXQuc3RvcmVzLm1hcChzID0+IHMuc3RvcmUuZ2V0Mih7IHBhdGg6IGNvbmZpZy5wYXRoLCByYW5nZTogY29uZmlnLnJhbmdlLCBpbmNsdWRlVG9tYnN0b25lczogY29uZmlnLmluY2x1ZGVUb21ic3RvbmVzLCBpbnRlcm5hbDogdHJ1ZSB9KSkpO1xuICAgIGxldCBiZXN0OiB7IGRhdGE6IEJ1ZmZlcjsgd3JpdGVUaW1lOiBudW1iZXI7IHNpemU6IG51bWJlciB9IHwgdW5kZWZpbmVkO1xuICAgIGZvciAobGV0IHJlc3VsdCBvZiByZXN1bHRzKSB7XG4gICAgICAgIGlmIChyZXN1bHQgJiYgKCFiZXN0IHx8IHJlc3VsdC53cml0ZVRpbWUgPiBiZXN0LndyaXRlVGltZSkpIHtcbiAgICAgICAgICAgIGJlc3QgPSByZXN1bHQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGJlc3Q7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRCdWNrZXRDb25maWcoYnVja2V0OiBCdWNrZXRTdGF0ZSk6IEFyY2hpdmVzQ29uZmlnIHtcbiAgICBsZXQgaW5kZXggPSB7IGZpbGVDb3VudDogMCwgYnl0ZUNvdW50OiAwIH07XG4gICAgbGV0IGluZGV4U291cmNlczogeyBkZWJ1Z05hbWU6IHN0cmluZzsgZmlsZUNvdW50OiBudW1iZXI7IGJ5dGVDb3VudDogbnVtYmVyIH1bXSA9IFtdO1xuICAgIGxldCBzeW5jaW5nOiBTeW5jQWN0aXZpdHlbXSA9IFtdO1xuICAgIGxldCByZWFkZXJEaXNrTGltaXQ6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgICBmb3IgKGxldCBzIG9mIGJ1Y2tldC5zdG9yZXMpIHtcbiAgICAgICAgbGV0IHByb2dyZXNzID0gcy5zdG9yZS5nZXRTeW5jUHJvZ3Jlc3MoKTtcbiAgICAgICAgaW5kZXguZmlsZUNvdW50ICs9IHByb2dyZXNzLmluZGV4LmZpbGVDb3VudDtcbiAgICAgICAgaW5kZXguYnl0ZUNvdW50ICs9IHByb2dyZXNzLmluZGV4LmJ5dGVDb3VudDtcbiAgICAgICAgaW5kZXhTb3VyY2VzLnB1c2goLi4ucHJvZ3Jlc3Muc291cmNlcyk7XG4gICAgICAgIHN5bmNpbmcucHVzaCguLi5wcm9ncmVzcy5zeW5jaW5nKTtcbiAgICAgICAgcmVhZGVyRGlza0xpbWl0ID0gcmVhZGVyRGlza0xpbWl0IHx8IHByb2dyZXNzLnJlYWRlckRpc2tMaW1pdDtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgLy8gRXZlcnkgc3RvcmUgaXMgaW5kZXgtYmFja2VkLCBzbyB0aGUgY2hhbmdlIGZlZWQgaXMgYWx3YXlzIG5hdGl2ZVxuICAgICAgICBzdXBwb3J0c0NoYW5nZXNBZnRlcjogdHJ1ZSxcbiAgICAgICAgcmVtb3RlQ29uZmlnOiBidWNrZXQucm91dGluZyxcbiAgICAgICAgaW5kZXgsXG4gICAgICAgIGluZGV4U291cmNlcyxcbiAgICAgICAgcmVhZGVyRGlza0xpbWl0LFxuICAgICAgICBzeW5jaW5nLFxuICAgIH07XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBidWNrZXRTeW5jU3RhdHVzKGJ1Y2tldDogQnVja2V0U3RhdGUpOiBQcm9taXNlPEFyY2hpdmVzU3luY1N0YXR1cz4ge1xuICAgIGxldCBzdGF0dXNlcyA9IGF3YWl0IFByb21pc2UuYWxsKGJ1Y2tldC5zdG9yZXMubWFwKHMgPT4gcy5zdG9yZS5nZXRTeW5jU3RhdHVzKCkpKTtcbiAgICByZXR1cm4ge1xuICAgICAgICBhbGxTY2Fuc0NvbXBsZXRlOiBzdGF0dXNlcy5ldmVyeSh4ID0+IHguYWxsU2NhbnNDb21wbGV0ZSksXG4gICAgICAgIGluZGV4U2l6ZTogc3RhdHVzZXMucmVkdWNlKChzdW0sIHgpID0+IHN1bSArIHguaW5kZXhTaXplLCAwKSxcbiAgICAgICAgc291cmNlczogc3RhdHVzZXMuZmxhdE1hcCh4ID0+IHguc291cmNlcyksXG4gICAgfTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlYnVnQnVja2V0SW5kZXhUb3RhbHMoYnVja2V0OiBCdWNrZXRTdGF0ZSk6IFByb21pc2U8eyBmaWxlQ291bnQ6IG51bWJlcjsgYnl0ZUNvdW50OiBudW1iZXI7IHNvdXJjZXM6IHsgZGVidWdOYW1lOiBzdHJpbmc7IGZpbGVDb3VudDogbnVtYmVyOyBieXRlQ291bnQ6IG51bWJlciB9W10gfT4ge1xuICAgIGxldCB0b3RhbHMgPSBhd2FpdCBQcm9taXNlLmFsbChidWNrZXQuc3RvcmVzLm1hcChzID0+IHMuc3RvcmUuY29tcHV0ZUluZGV4VG90YWxzKCkpKTtcbiAgICByZXR1cm4ge1xuICAgICAgICBmaWxlQ291bnQ6IHRvdGFscy5yZWR1Y2UoKHN1bSwgeCkgPT4gc3VtICsgeC5maWxlQ291bnQsIDApLFxuICAgICAgICBieXRlQ291bnQ6IHRvdGFscy5yZWR1Y2UoKHN1bSwgeCkgPT4gc3VtICsgeC5ieXRlQ291bnQsIDApLFxuICAgICAgICBzb3VyY2VzOiB0b3RhbHMuZmxhdE1hcCh4ID0+IHguc291cmNlcyksXG4gICAgfTtcbn1cblxuY29uc3QgYnVja2V0cyA9IG5ldyBNYXA8c3RyaW5nLCBQcm9taXNlPEJ1Y2tldFN0YXRlIHwgdW5kZWZpbmVkPj4oKTtcbi8vIFRoZSByZXNvbHZlZCBvbmVzLCBmb3IgdGhlIGNvZGUgdGhhdCB3YWxrcyBidWNrZXRzIHJhdGhlciB0aGFuIGFza2luZyBmb3Igb25lIChzZWUgZ2V0QnVja2V0U3RhdGVzKVxuY29uc3QgbG9hZGVkQnVja2V0cyA9IG5ldyBNYXA8c3RyaW5nLCBCdWNrZXRTdGF0ZT4oKTtcblxuLyoqIFRoZSBidWNrZXQgc3RhdGVzIGN1cnJlbnRseSBpbiBtZW1vcnkgLSB3aGF0IHRoZSBzd2l0Y2hvdmVyIG1hY2hpbmVyeSB3YWxrcy4gT25seSB3aGF0IGlzIGxvYWRlZDogbG9hZGluZyBhIGJ1Y2tldCBzdGFydHMgaXRzIHN5bmNocm9uaXphdGlvbiwgYW5kIGEgYnVja2V0IG5vdGhpbmcgaGFzIHRvdWNoZWQgaGFzIG5vIGluLWZsaWdodCB3cml0ZXMgdG8gaGFuZCBvdmVyIGFueXdheS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRCdWNrZXRTdGF0ZXMoKTogQnVja2V0U3RhdGVbXSB7XG4gICAgcmV0dXJuIFsuLi5sb2FkZWRCdWNrZXRzLnZhbHVlcygpXTtcbn1cblxuY29uc3QgcmVzb2x2ZWRTb3VyY2VBcmNoaXZlcyA9IG5ldyBNYXA8c3RyaW5nLCBJQXJjaGl2ZXM+KCk7XG4vKiogQSBjYWNoZWQgSUFyY2hpdmVzIGZvciBhIHBlcnNpc3RlZCBzb3VyY2UgaWRlbnRpdHk6IGEgcm91dGluZyBVUkwgKGhvc3RlZC9iYWNrYmxhemUpIG9yIGEgZGlzayBmb2xkZXIgcGF0aCAtIHRoZSBmb3JtIEJsb2JTdG9yZSdzIHNvdXJjZXMgbGlzdCBzdG9yZXMuIENvbmZpZ3VyYXRpb24gKHZhbGlkIHdpbmRvd3MsIHJvdXRlcykgZGVjaWRlcyBXSEVOIGEgc291cmNlIHNob3VsZCBiZSB1c2VkOyBmb3IgcmVhZGluZyBieXRlcyB0aGUgaW5kZXggc2F5cyBhIHNvdXJjZSBob2xkcywgdGhlIFVSTCBhbG9uZSBpcyBlbm91Z2ggLSBldmVuIGZvciBzb3VyY2VzIG5vIGxvbmdlciBpbiBhbnkgY29uZmlnLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVTb3VyY2VBcmNoaXZlcyh1cmw6IHN0cmluZyk6IElBcmNoaXZlcyB7XG4gICAgbGV0IGV4aXN0aW5nID0gcmVzb2x2ZWRTb3VyY2VBcmNoaXZlcy5nZXQodXJsKTtcbiAgICBpZiAoZXhpc3RpbmcpIHJldHVybiBleGlzdGluZztcbiAgICBsZXQgc291cmNlQ29uZmlnOiBTb3VyY2VDb25maWcgfCB1bmRlZmluZWQ7XG4gICAgaWYgKHVybC5zdGFydHNXaXRoKFwiaHR0cHM6Ly9cIikpIHtcbiAgICAgICAgLy8gVGhlIGNvbmZpZyBpcyBmYWJyaWNhdGVkIGZyb20gdGhlIGJhcmUgVVJMIGFuZCBjYW4gbmV2ZXIgZXhhY3QtbWF0Y2ggYSBzZXJ2ZXIncyBlbnRyaWVzIC0gd2hpY2ggaXMgZmluZSwgYmVjYXVzZSBob2xkZXIgcmVhZHMgYXJlIGludGVybmFsIHJlYWRzLCBhbmQgaW50ZXJuYWwgcmVhZHMgbmV2ZXIgc2VsZWN0IGEgc3RvcmUgKHNlZSByZWFkQnVja2V0SW50ZXJuYWwpXG4gICAgICAgIHNvdXJjZUNvbmZpZyA9IG5vcm1hbGl6ZVNvdXJjZSh1cmwpO1xuICAgIH1cbiAgICBsZXQgYXJjaGl2ZXMgPSBjcmVhdGVTdG9yZVNvdXJjZSh7IHNvdXJjZUNvbmZpZywgZm9sZGVyOiB1cmwgfSk7XG4gICAgcmVzb2x2ZWRTb3VyY2VBcmNoaXZlcy5zZXQodXJsLCBhcmNoaXZlcyk7XG4gICAgcmV0dXJuIGFyY2hpdmVzO1xufVxuXG4vKiogV2hhdCBhbiBpbmRleCBlbnRyeSByZWNvcmRzIGFzIHRoZSBob2xkZXIgb2YgaXRzIGJ5dGVzIChzZWUgQXJjaGl2ZXNTb3VyY2UudXJsKSwgc28gaXQgbXVzdCBuYW1lIHRoZSBlbmRwb2ludCBGT1JFVkVSLiBBbiBpbnRlcm1lZGlhdGUgaXMgYSBzd2l0Y2hvdmVyJ3MgdGVtcG9yYXJ5IGFsdGVybmF0ZSBwb3J0IG9udG8gYW5vdGhlciBzb3VyY2UsIGFuZCB0aGF0IHBvcnQgaXMgZ29uZSBmb3IgZ29vZCBvbmNlIGl0cyB3aW5kb3cgcGFzc2VzIC0gc28gaXQgaXMgcmVjb3JkZWQgYXMgdGhlIHNvdXJjZSBpdCB3YXMgc3BsaXQgb3V0IG9mLCB3aGljaCBob2xkcyB0aGUgc2FtZSBidWNrZXQgYW5kIG91dGxpdmVzIGl0LiAqL1xuZnVuY3Rpb24gc291cmNlUGVyc2lzdGVudFVybChzb3VyY2VDb25maWc6IFNvdXJjZUNvbmZpZyB8IHVuZGVmaW5lZCwgZm9sZGVyOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGlmICghc291cmNlQ29uZmlnKSByZXR1cm4gZm9sZGVyO1xuICAgIHJldHVybiBzb3VyY2VDb25maWcuaW50ZXJtZWRpYXRlIHx8IHNvdXJjZUNvbmZpZy51cmw7XG59XG5cbi8qKiBUaGUgZmFzdC13cml0ZSBwb2xpY3kgdGhpcyBzdG9yZSB3cml0ZXMgdW5kZXI6IGl0cyBvd24gY29uZmlndXJhdGlvbiBkZWNpZGVzIGl0IChmYXN0L3dyaXRlRGVsYXkgYXJlIE9VUiBzZXR0aW5ncywgbm90IHRoZSBwZWVyJ3MpLCBhbmQgZWFjaCBzb3VyY2UgdGhlbiBob2xkcyB3cml0ZXMgZm9yIGFzIGxvbmcgYXMgc291cmNlV3JpdGVEZWxheSBzYXlzLiAqL1xuLyoqXG4gKiBFdmVyeSBzdG9yZSB0aGlzIHByb2Nlc3MgcnVucywgYnkgZm9sZGVyIC0gd2hpY2ggSVMgdGhlIHN0b3JlJ3MgaWRlbnRpdHk6IGFjY291bnQsIG5hbWUsIGJ1Y2tldC5cbiAqIEEgc3RvcmUgaXMgbWFkZSBvbmNlLCBjb25maWd1cmVzIGl0c2VsZiBmcm9tIHRoZSByb3V0aW5nIGNvbmZpZyBpdCBob2xkcywgYW5kIHN0YXlzOyBub3RoaW5nIGhlcmVcbiAqIGRlY2lkZXMgd2hhdCBpdCBpcywgb25seSB0aGF0IGl0IGV4aXN0cy5cbiAqL1xuY29uc3Qgc3RvcmVzID0gbmV3IE1hcDxzdHJpbmcsIEJsb2JTdG9yZT4oKTtcblxuZXhwb3J0IGZ1bmN0aW9uIGdldFN0b3JlKGFjY291bnQ6IHN0cmluZywgYnVja2V0TmFtZTogc3RyaW5nLCBuYW1lOiBzdHJpbmcpOiBCbG9iU3RvcmUge1xuICAgIC8vIFRoZSBvbmUgcGxhY2UgYSBuYW1lIGJlY29tZXMgYSBmb2xkZXIsIHNvIHRoZSBvbmUgcGxhY2UgaXQgaXMgdmFsaWRhdGVkIChpdCBjYW4gY29tZSBzdHJhaWdodCBvZmYgdGhlIHdpcmUpXG4gICAgYXNzZXJ0VmFsaWRTb3VyY2VOYW1lKG5hbWUpO1xuICAgIGxldCBmb2xkZXIgPSBnZXRCdWNrZXRGb2xkZXIobmFtZSwgYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgbGV0IGV4aXN0aW5nID0gc3RvcmVzLmdldChmb2xkZXIpO1xuICAgIGlmIChleGlzdGluZykgcmV0dXJuIGV4aXN0aW5nO1xuICAgIGNvbnNvbGUubG9nKGBPcGVuaW5nIHN0b3JlICR7SlNPTi5zdHJpbmdpZnkobmFtZSl9IG9mIGJ1Y2tldCAke2FjY291bnR9LyR7YnVja2V0TmFtZX0gKGZvbGRlciAke2ZvbGRlcn0pIC0gY3JlYXRlZCBvbiB0aGlzIGZpcnN0IHVzZSBpZiBpdCBuZXZlciBleGlzdGVkYCk7XG4gICAgbGV0IHN0b3JlID0gbmV3IEJsb2JTdG9yZShmb2xkZXIsIG5hbWUsIHtcbiAgICAgICAgLy8gV2hpY2ggZW50cmllcyBpbiBJVFMgcm91dGluZyBjb25maWcgYXJlIHRoaXMgc2VydmVyJ3MgY29weSBvZiBpdFxuICAgICAgICBpc1NlbGY6IHNvdXJjZSA9PiBpc1NlbGZTb3VyY2Uoc291cmNlLCBhY2NvdW50LCBidWNrZXROYW1lKSxcbiAgICAgICAgY3JlYXRlU291cmNlOiBjb25maWcgPT4gY3JlYXRlU3RvcmVTb3VyY2UoeyBzb3VyY2VDb25maWc6IGNvbmZpZy5zb3VyY2VDb25maWcsIGZvbGRlciwgd3JpdGVEZWxheTogY29uZmlnLndyaXRlRGVsYXkgfSksXG4gICAgICAgIGFwcGx5U291cmNlOiAoc291cmNlLCBzb3VyY2VDb25maWcsIHdyaXRlRGVsYXkpID0+IGFwcGx5U291cmNlQ29uZmlnKHNvdXJjZSwgc291cmNlQ29uZmlnLCB3cml0ZURlbGF5KSxcbiAgICAgICAgb25Xcml0ZUNvdW50ZWQ6IChraW5kLCBieXRlcykgPT4gY291bnRCdWNrZXRXcml0ZShgJHthY2NvdW50fS8ke2J1Y2tldE5hbWV9YCwga2luZCwgYnl0ZXMpLFxuICAgICAgICByZXNvbHZlU291cmNlVXJsOiByZXNvbHZlU291cmNlQXJjaGl2ZXMsXG4gICAgfSk7XG4gICAgc3RvcmVzLnNldChmb2xkZXIsIHN0b3JlKTtcbiAgICAvLyBMYXp5IGluaXQgd291bGQgbGVhdmUgYSBzdG9yZSBub3RoaW5nIGhhcyB0b3VjaGVkIHNpdHRpbmcgaW5lcnQgLSBubyBpbmRleCBsb2FkZWQsIG5vIGNvbmZpZyBhcHBsaWVkLCBub3RoaW5nIHN5bmNocm9uaXppbmcgLSB3aGlsZSBpdHMgZm9sZGVyIGlzIGZ1bGwgb2YgZmlsZXNcbiAgICB2b2lkIHN0b3JlLmluaXQoKS5jYXRjaCgoZTogRXJyb3IpID0+IGNvbnNvbGUuZXJyb3IoYEluaXRpYWxpemluZyBzdG9yZSAke0pTT04uc3RyaW5naWZ5KG5hbWUpfSBvZiBidWNrZXQgJHthY2NvdW50fS8ke2J1Y2tldE5hbWV9IGZhaWxlZDogJHtlLnN0YWNrID8/IGV9YCkpO1xuICAgIHJldHVybiBzdG9yZTtcbn1cblxuLyoqIFRoZSBidWNrZXQgYXMgdGhpcyBzZXJ2ZXIgaGFzIGl0OiB0aGUgc3RvcmVzIHdob3NlIGZvbGRlcnMgZXhpc3QsIHBsdXMgd2hhdGV2ZXIgdGhlIG5ld2VzdCBvZiB0aGVpciBjb25maWdzIHNheXMgYWJvdXQgdXMuIE5hbWVzIGNvbWUgZnJvbSB0aGUgRElTSywgbm90IGZyb20gdGhlIGNvbmZpZyAtIGEgc3RvcmUgd2UgaG9sZCBrZWVwcyBiZWluZyBzZXJ2ZWQgd2hldGhlciBvciBub3QgdGhlIGN1cnJlbnQgY29uZmlnIHN0aWxsIG1lbnRpb25zIGl0LiAqL1xuZnVuY3Rpb24gYnVpbGRCdWNrZXQoYWNjb3VudDogc3RyaW5nLCBidWNrZXROYW1lOiBzdHJpbmcsIG5hbWVzOiBzdHJpbmdbXSwgcm91dGluZzogUmVtb3RlQ29uZmlnIHwgdW5kZWZpbmVkKTogQnVja2V0U3RhdGUge1xuICAgIGxldCBwbGFuID0gcm91dGluZyAmJiBwbGFuU2VsZlN0b3JlcyhhY2NvdW50LCBidWNrZXROYW1lLCByb3V0aW5nKSB8fCB1bmRlZmluZWQ7XG4gICAgbGV0IGVudHJpZXNCeU5hbWUgPSBuZXcgTWFwPHN0cmluZywgSG9zdGVkQ29uZmlnW10+KCk7XG4gICAgZm9yIChsZXQgc2VsZlN0b3JlIG9mIHBsYW4/LnN0b3JlcyB8fCBbXSkge1xuICAgICAgICBlbnRyaWVzQnlOYW1lLnNldChzZWxmU3RvcmUubmFtZSwgc2VsZlN0b3JlLmVudHJpZXMpO1xuICAgIH1cbiAgICAvLyBFYWNoIHN0b3JlIHJlYWRzIGl0cyBvd24gY29weSBvZiB0aGUgY29uZmlnIGFuZCBkZWNpZGVzIHdoYXQgaXQgaXMgLSBzZWUgQmxvYlN0b3JlLmFwcGx5Um91dGluZ0NvbmZpZy4gTm90aGluZyBoZXJlIGNvbmZpZ3VyZXMgYW55dGhpbmcuXG4gICAgbGV0IHN0b3JlczogTG9hZGVkU3RvcmVbXSA9IG5hbWVzLm1hcChuYW1lID0+ICh7XG4gICAgICAgIG5hbWUsXG4gICAgICAgIGVudHJpZXM6IGVudHJpZXNCeU5hbWUuZ2V0KG5hbWUpIHx8IFtdLFxuICAgICAgICBmb2xkZXI6IGdldEJ1Y2tldEZvbGRlcihuYW1lLCBhY2NvdW50LCBidWNrZXROYW1lKSxcbiAgICAgICAgc3RvcmU6IGdldFN0b3JlKGFjY291bnQsIGJ1Y2tldE5hbWUsIG5hbWUpLFxuICAgIH0pKTtcbiAgICBsZXQgbG9hZGVkOiBCdWNrZXRTdGF0ZSA9IHsgYWNjb3VudCwgYnVja2V0TmFtZSwgcm91dGluZywgc2VsZkVudHJpZXM6IHBsYW4/LnNlbGZFbnRyaWVzIHx8IFtdLCBzZWxmOiBwbGFuPy5zZWxmLCBzdG9yZXMgfTtcbiAgICBsb2FkZWRCdWNrZXRzLnNldChgJHthY2NvdW50fS8ke2J1Y2tldE5hbWV9YCwgbG9hZGVkKTtcbiAgICBzY2hlZHVsZUJvdW5kYXJ5V29yayhsb2FkZWQpO1xuICAgIHJldHVybiBsb2FkZWQ7XG59XG5cbi8vIEEgYnVja2V0IGV4aXN0cyBoZXJlIHdoZW4gaXQgaGFzIGF0IGxlYXN0IG9uZSBzdG9yZSBmb2xkZXIgLSB0aGUgZGlzayBJUyB0aGUgcmVjb3JkLiBJdHMgY29uZmlnIGlzIHRoZSBuZXdlc3QgY29weSBhbW9uZyB0aG9zZSBzdG9yZXM7IHdpdGggbm9uZSBhdCBhbGwgaXQgaGFzIG5vIGNvbmZpZyB5ZXQsIHdoaWNoIGlzIGEgcGVyZmVjdGx5IGdvb2Qgc3RhdGUgZm9yIGEgc3RvcmUgbm9ib2R5IGhhcyBjb25maWd1cmVkLlxuYXN5bmMgZnVuY3Rpb24gbG9hZEJ1Y2tldChhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZyk6IFByb21pc2U8QnVja2V0U3RhdGUgfCB1bmRlZmluZWQ+IHtcbiAgICBsZXQgZm9sZGVycyA9IGF3YWl0IGxpc3RCdWNrZXRTdG9yZUZvbGRlcnMoYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgaWYgKCFmb2xkZXJzLmxlbmd0aCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBsZXQgcm91dGluZyA9IGF3YWl0IHJlYWRSb3V0aW5nRnJvbURpc2soYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgcmV0dXJuIGJ1aWxkQnVja2V0KGFjY291bnQsIGJ1Y2tldE5hbWUsIGZvbGRlcnMubWFwKHggPT4geC5uYW1lKSwgcm91dGluZyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRMb2FkZWRCdWNrZXQoYWNjb3VudDogc3RyaW5nLCBidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPEJ1Y2tldFN0YXRlIHwgdW5kZWZpbmVkPiB7XG4gICAgbGV0IGtleSA9IGAke2FjY291bnR9LyR7YnVja2V0TmFtZX1gO1xuICAgIHJldHVybiBidWNrZXRzLmdldChrZXkpIHx8IHJlbG9hZEJ1Y2tldChhY2NvdW50LCBidWNrZXROYW1lKTtcbn1cblxuLyoqIFJlLXJlYWRzIHRoZSBidWNrZXQgb2ZmIHRoZSBkaXNrLCByZXBsYWNpbmcgdGhlIGNhY2hlZCBzbmFwc2hvdDogd2hhdCBhIHJvdXRpbmctY29uZmlnIHdyaXRlIGNhbGxzLCBiZWNhdXNlIHRoYXQgd3JpdGUgY2FuIENSRUFURSBhIHN0b3JlIChhIG5ldyBuYW1lIGdldHMgYSBuZXcgZm9sZGVyKSBhbmQgdGhlIHNuYXBzaG90IHdvdWxkIGtlZXAgYW5zd2VyaW5nIHdpdGggdGhlIHN0b3JlcyBpdCBzYXcgYXQgbG9hZCB0aW1lLiBFeGlzdGluZyBzdG9yZXMgYXJlIHJldXNlZCAoZ2V0U3RvcmUgY2FjaGVzIGJ5IGZvbGRlciksIHNvIHRoaXMgb25seSBwaWNrcyB1cCBmb2xkZXIgY2hhbmdlcyAtIGl0IG5ldmVyIHJlc3RhcnRzIGEgc3RvcmUuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVsb2FkQnVja2V0KGFjY291bnQ6IHN0cmluZywgYnVja2V0TmFtZTogc3RyaW5nKTogUHJvbWlzZTxCdWNrZXRTdGF0ZSB8IHVuZGVmaW5lZD4ge1xuICAgIGxldCBrZXkgPSBgJHthY2NvdW50fS8ke2J1Y2tldE5hbWV9YDtcbiAgICBsZXQgbG9hZGVkID0gbG9hZEJ1Y2tldChhY2NvdW50LCBidWNrZXROYW1lKTtcbiAgICBidWNrZXRzLnNldChrZXksIGxvYWRlZCk7XG4gICAgdm9pZCBsb2FkZWQudGhlbihidWNrZXQgPT4ge1xuICAgICAgICBpZiAoIWJ1Y2tldCAmJiBidWNrZXRzLmdldChrZXkpID09PSBsb2FkZWQpIHtcbiAgICAgICAgICAgIGJ1Y2tldHMuZGVsZXRlKGtleSk7XG4gICAgICAgIH1cbiAgICB9LCAoKSA9PiB7XG4gICAgICAgIGlmIChidWNrZXRzLmdldChrZXkpID09PSBsb2FkZWQpIHtcbiAgICAgICAgICAgIGJ1Y2tldHMuZGVsZXRlKGtleSk7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gYXdhaXQgbG9hZGVkO1xufVxuXG4vKipcbiAqIFdyaXRpbmcgdGhlIHJvdXRpbmcgY29uZmlnIGlzIGEgd3JpdGUgbGlrZSBhbnkgb3RoZXI6IGl0IGdvZXMgaW50byBhIHN0b3JlLCBhbmQgdGhlIHN0b3JlIGFwcGxpZXNcbiAqIGl0IHRvIGl0c2VsZiBhbmQgbGV0cyBpdHMgcGVlcnMgcHVsbCBpdC4gVGhlIG9ubHkgdGhpbmcgdGhhdCBoYXBwZW5zIGhlcmUgaXMgcGlja2luZyBXSElDSCBzdG9yZSxcbiAqIGJlY2F1c2UgdGhlIHdyaXRlciBuYW1lcyBhIHNvdXJjZSBhbmQgYSBzb3VyY2UgbmFtZXMgYSBzdG9yZS5cbiAqXG4gKiBJbi1mbGlnaHQgc3dpdGNob3ZlciB3aW5kb3dzIGFyZSByZS1pbmplY3RlZCBmaXJzdCAoc2VlIGludGVybWVkaWF0ZU1hbmFnZW1lbnQpOiBhbiBvcGVyYXRvcidzXG4gKiBjb25maWcga25vd3Mgbm90aGluZyBhYm91dCBhIHN3aXRjaG92ZXIgdGhhdCBpcyBoYXBwZW5pbmcgcmlnaHQgbm93LCBhbmQgd3JpdGluZyBpdCBhcy1pcyB3b3VsZFxuICogY2FuY2VsIGl0IG1pZC1mbGlnaHQuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB3cml0ZVJvdXRpbmdDb25maWcoYWNjb3VudDogc3RyaW5nLCBidWNrZXROYW1lOiBzdHJpbmcsIG5hbWU6IHN0cmluZywgZGF0YTogQnVmZmVyLCBjb25maWc/OiB7IGxhc3RNb2RpZmllZD86IG51bWJlciB9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXNzZXJ0V3JpdGVzQWxsb3dlZCgpO1xuICAgIGxldCBzdG9yZSA9IGdldFN0b3JlKGFjY291bnQsIGJ1Y2tldE5hbWUsIG5hbWUpO1xuICAgIGxldCBpbmNvbWluZyA9IHBhcnNlUm91dGluZ0RhdGEoZGF0YSk7XG4gICAgbGV0IGN1cnJlbnQgPSAoYXdhaXQgZ2V0TG9hZGVkQnVja2V0KGFjY291bnQsIGJ1Y2tldE5hbWUpKT8ucm91dGluZztcbiAgICBsZXQgc3RvcmVkID0gcmVpbmplY3RJbnRlcm1lZGlhdGVzKGN1cnJlbnQsIGluY29taW5nKTtcbiAgICBhd2FpdCBzdG9yZS5zZXQoeyBwYXRoOiBST1VUSU5HX0ZJTEUsIGRhdGE6IEJ1ZmZlci5mcm9tKHNlcmlhbGl6ZVJlbW90ZUNvbmZpZyhzdG9yZWQpKSwgbGFzdE1vZGlmaWVkOiBjb25maWc/Lmxhc3RNb2RpZmllZCB9KTtcbiAgICAvLyBUaGUgd3JpdGUgbWF5IGhhdmUgQ1JFQVRFRCB0aGUgc3RvcmUgKGEgbmV3IG5hbWUgZ2V0cyBhIG5ldyBmb2xkZXIpLCBhbmQgdGhlIGxvYWRlZCBidWNrZXQgaXMgYSBzbmFwc2hvdCBvZiB0aGUgZGlzayAtIHNvIGl0IGlzIHJlLXJlYWQsIG9yIGV2ZXJ5IGRhdGEgd3JpdGUgbmFtaW5nIHRoZSBuZXcgc3RvcmUgaXMgcmVqZWN0ZWQgdW50aWwgYSByZXN0YXJ0XG4gICAgYXdhaXQgcmVsb2FkQnVja2V0KGFjY291bnQsIGJ1Y2tldE5hbWUpO1xuICAgIGJyb2FkY2FzdFJvdXRpbmdDaGFuZ2VkKCk7XG59XG5cbi8qKiBXaGljaCBidWNrZXRzIHRoaXMgcHJvY2VzcyBjdXJyZW50bHkgaGFzIGxvYWRlZCAtIHdoYXQgYSBkZXBsb3kgc3VjY2Vzc29yIGFza3MgaXRzIHByZWRlY2Vzc29yIGZvciwgc28gaXQgYWN0aXZhdGVzIGV4YWN0bHkgdGhlIGJ1Y2tldHMgdGhhdCBhcmUgYWN0dWFsbHkgaW4gdXNlLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEFjdGl2ZUJ1Y2tldEtleXMoKTogeyBhY2NvdW50OiBzdHJpbmc7IGJ1Y2tldE5hbWU6IHN0cmluZyB9W10ge1xuICAgIHJldHVybiBbLi4uYnVja2V0cy5rZXlzKCldLm1hcChrZXkgPT4ge1xuICAgICAgICBsZXQgc2xhc2ggPSBrZXkuaW5kZXhPZihcIi9cIik7XG4gICAgICAgIHJldHVybiB7IGFjY291bnQ6IGtleS5zbGljZSgwLCBzbGFzaCksIGJ1Y2tldE5hbWU6IGtleS5zbGljZShzbGFzaCArIDEpIH07XG4gICAgfSk7XG59XG5cbmV4cG9ydCB0eXBlIFNlcnZlckJ1Y2tldEluZm8gPSB7XG4gICAgYnVja2V0TmFtZTogc3RyaW5nO1xuICAgIGFjdGl2ZTogYm9vbGVhbjtcbiAgICAvKiogV2hlcmUgdGhlIGJ1Y2tldCdzIGRhdGEgbGl2ZXMgb24gdGhpcyBzZXJ2ZXIgKi9cbiAgICBmb2xkZXI6IHN0cmluZztcbiAgICAvKiogVGhlIGRyaXZlIHRoYXQgZm9sZGVyIGlzIG9uLiBCdWNrZXRzIHNoYXJpbmcgYSBkcml2ZSByZXBvcnQgdGhlIHNhbWUgbnVtYmVycy4gKi9cbiAgICBkaXNrPzogQnVja2V0RGlza0luZm87XG4gICAgZGlza0Vycm9yPzogc3RyaW5nO1xuICAgIHdyaXRlU3RhdHM/OiBCdWNrZXRXcml0ZVN0YXRzO1xuICAgIGNvbmZpZz86IEFyY2hpdmVzQ29uZmlnO1xuICAgIGVycm9yPzogc3RyaW5nO1xufTtcblxuZXhwb3J0IHR5cGUgQWN0aXZlQnVja2V0SW5mbyA9IHtcbiAgICBmb2xkZXI6IHN0cmluZztcbiAgICAvKiogVGhlIHJvdXRpbmcgY29uZmlnIHRoZSBidWNrZXQgaXMgUlVOTklORyBvbiwgc3RyYWlnaHQgZnJvbSBtZW1vcnkgLSBpbmNsdWRpbmcgc3dpdGNob3ZlciB3aW5kb3dzIHdyaXR0ZW4gc2luY2UgaXQgbG9hZGVkLiBBYnNlbnQgd2hlbiBub25lIG9mIGl0cyBzdG9yZXMgaGFzIG9uZSB5ZXQuICovXG4gICAgcm91dGluZz86IFJlbW90ZUNvbmZpZztcbiAgICAvKiogT3VyIG93biBlbnRyaWVzIGluIHRoYXQgY29uZmlnLCBhbmQgdGhlaXIgc3VtbWFyaXplZCBjdXJyZW50IHJvbGUgKHJvdXRlcyB1bmlvbiArIGZsYWdzKSAqL1xuICAgIHNlbGZFbnRyaWVzOiBIb3N0ZWRDb25maWdbXTtcbiAgICBzZWxmPzogU2VsZlN1bW1hcnk7XG4gICAgY29uZmlnOiBBcmNoaXZlc0NvbmZpZztcbn07XG5cbmZ1bmN0aW9uIHRvQWN0aXZlQnVja2V0SW5mbyhsb2FkZWQ6IEJ1Y2tldFN0YXRlKTogQWN0aXZlQnVja2V0SW5mbyB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgLy8gT25lIG9mIGl0cyBzdG9yZXMnIGZvbGRlcnMgLSBhIGJ1Y2tldCBubyBsb25nZXIgaGFzIGEgZm9sZGVyIG9mIGl0cyBvd24sIGl0IGhhcyBvbmUgcGVyIHN0b3JlXG4gICAgICAgIGZvbGRlcjogbG9hZGVkLnN0b3Jlc1swXT8uZm9sZGVyIHx8IFwiXCIsXG4gICAgICAgIHJvdXRpbmc6IGxvYWRlZC5yb3V0aW5nLFxuICAgICAgICBzZWxmRW50cmllczogbG9hZGVkLnNlbGZFbnRyaWVzLFxuICAgICAgICBzZWxmOiBsb2FkZWQuc2VsZixcbiAgICAgICAgY29uZmlnOiBnZXRCdWNrZXRDb25maWcobG9hZGVkKSxcbiAgICB9O1xufVxuXG4vKiogVGhlIGxpdmUgaW4tbWVtb3J5IHN0YXRlIG9mIE9ORSBidWNrZXQsIGFuc3dlcmVkIHdpdGhvdXQgdG91Y2hpbmcgdGhlIGRpc2sgKG5vIHJvdXRpbmcgZmlsZSByZWFkLCBubyBzdGF0ZnMsIG5vIHN0b3JlZCB3cml0ZSBzdGF0cykuIFJldHVybnMgYW4gZXJyb3Igc3RyaW5nIHdoZW4gdGhlIGJ1Y2tldCBpcyBub3QgbG9hZGVkIGhlcmUsIHdoaWNoIGlzIHRoZSBub3JtYWwgc3RhdGUgZm9yIGEgYnVja2V0IG5vdGhpbmcgaGFzIGFjY2Vzc2VkIHNpbmNlIHN0YXJ0dXAuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZGVidWdHZXRBY3RpdmVCdWNrZXQoYWNjb3VudDogc3RyaW5nLCBidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPEFjdGl2ZUJ1Y2tldEluZm8gfCBzdHJpbmc+IHtcbiAgICBsZXQga2V5ID0gYCR7YWNjb3VudH0vJHtidWNrZXROYW1lfWA7XG4gICAgbGV0IGxvYWRlZFByb21pc2UgPSBidWNrZXRzLmdldChrZXkpO1xuICAgIGlmICghbG9hZGVkUHJvbWlzZSkge1xuICAgICAgICByZXR1cm4gYEJ1Y2tldCAke2tleX0gaXMgbm90IGxvYWRlZCBvbiB0aGlzIHNlcnZlciwgc28gaXQgaGFzIG5vIGxpdmUgc3RhdGUgKGl0IGxvYWRzIG9uIGZpcnN0IGFjY2VzcylgO1xuICAgIH1cbiAgICBsZXQgbG9hZGVkOiBCdWNrZXRTdGF0ZSB8IHVuZGVmaW5lZDtcbiAgICB0cnkge1xuICAgICAgICBsb2FkZWQgPSBhd2FpdCBsb2FkZWRQcm9taXNlO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmV0dXJuIGBCdWNrZXQgJHtrZXl9IGZhaWxlZCB0byBsb2FkIG9uIHRoaXMgc2VydmVyOiAke1N0cmluZygoZSBhcyBFcnJvcikuc3RhY2sgPz8gZSkuc2xpY2UoMCwgNTAwKX1gO1xuICAgIH1cbiAgICBpZiAoIWxvYWRlZCkge1xuICAgICAgICByZXR1cm4gYEJ1Y2tldCAke2tleX0gZG9lcyBub3QgZXhpc3Qgb24gdGhpcyBzZXJ2ZXJgO1xuICAgIH1cbiAgICByZXR1cm4gdG9BY3RpdmVCdWNrZXRJbmZvKGxvYWRlZCk7XG59XG5cbi8qKiBMb2FkcyBhIGJ1Y2tldCB0aGF0IGV4aXN0cyBvbiB0aGlzIHNlcnZlcidzIGRpc2sgaW50byBtZW1vcnksIHdoaWNoIHN0YXJ0cyBpdHMgc3luY2hyb25pemF0aW9uIGFuZCB3aW5kb3cgdGltZXJzLCBhbmQgcmV0dXJucyBpdHMgbGl2ZSBzdGF0ZS4gTm90aGluZyBpcyB3cml0dGVuIGFuZCBubyBvdGhlciBzZXJ2ZXIgaXMgY29udGFjdGVkIC0gdW5saWtlIGJ1aWxkaW5nIGFuIEFyY2hpdmVzQ2hhaW4gZm9yIGl0LCB3aGljaCB3b3VsZCBwcm9iZSBldmVyeSBzb3VyY2UgYW5kIGNvdWxkIHdyaXRlIHRoZSByb3V0aW5nIGNvbmZpZy4gQWxyZWFkeS1sb2FkZWQgYnVja2V0cyBqdXN0IHJldHVybiB0aGVpciBzdGF0ZS4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhY3RpdmF0ZUJ1Y2tldChhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZyk6IFByb21pc2U8QWN0aXZlQnVja2V0SW5mbyB8IHN0cmluZz4ge1xuICAgIGxldCBrZXkgPSBgJHthY2NvdW50fS8ke2J1Y2tldE5hbWV9YDtcbiAgICBsZXQgd2FzTG9hZGVkID0gYnVja2V0cy5oYXMoa2V5KTtcbiAgICBsZXQgbG9hZGVkOiBCdWNrZXRTdGF0ZSB8IHVuZGVmaW5lZDtcbiAgICB0cnkge1xuICAgICAgICBsb2FkZWQgPSBhd2FpdCBnZXRMb2FkZWRCdWNrZXQoYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZXR1cm4gYEJ1Y2tldCAke2tleX0gZmFpbGVkIHRvIGxvYWQgb24gdGhpcyBzZXJ2ZXI6ICR7U3RyaW5nKChlIGFzIEVycm9yKS5zdGFjayA/PyBlKS5zbGljZSgwLCA1MDApfWA7XG4gICAgfVxuICAgIGlmICghbG9hZGVkKSB7XG4gICAgICAgIHJldHVybiBgQnVja2V0ICR7a2V5fSBkb2VzIG5vdCBleGlzdCBvbiB0aGlzIHNlcnZlciAoaXQgaGFzIG5vIHN0b3JlIGZvbGRlcnMgdW5kZXIgJHtnZXRCdWNrZXRGb2xkZXIoXCI8bmFtZT5cIiwgYWNjb3VudCwgYnVja2V0TmFtZSl9KWA7XG4gICAgfVxuICAgIC8vIFdhaXQgZm9yIHRoZSBpbmRleGVzIHRvIGxvYWQsIHNvIHRoZSB0b3RhbHMgd2UgcmV0dXJuIGFyZSB0aGUgcmVhbCBvbmVzIHJhdGhlciB0aGFuIHplcm9lcyBmcm9tIHN0b3JlcyB0aGF0IGhhdmUgbm90IHJlYWQgdGhlaXIgaW5kZXggeWV0LiBUaGUgc291cmNlIHNjYW5zIGtlZXAgcnVubmluZyBpbiB0aGUgYmFja2dyb3VuZC5cbiAgICBmb3IgKGxldCBzIG9mIGxvYWRlZC5zdG9yZXMpIHtcbiAgICAgICAgYXdhaXQgcy5zdG9yZS5pbml0KCk7XG4gICAgfVxuICAgIGlmICghd2FzTG9hZGVkKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBBY3RpdmF0ZWQgYnVja2V0ICR7a2V5fSBvbiByZXF1ZXN0OiBpdCBpcyBub3cgbG9hZGVkIGFuZCBzeW5jaHJvbml6aW5nYCk7XG4gICAgfVxuICAgIHJldHVybiB0b0FjdGl2ZUJ1Y2tldEluZm8obG9hZGVkKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlYnVnTGlzdEFjY291bnRCdWNrZXRzKGFjY291bnQ6IHN0cmluZyk6IFByb21pc2U8U2VydmVyQnVja2V0SW5mb1tdPiB7XG4gICAgbGV0IHN0YXJ0ID0gRGF0ZS5ub3coKTtcbiAgICBsZXQgdGltaW5ncyA9IG5ldyBNYXA8c3RyaW5nLCBudW1iZXI+KCk7XG4gICAgYXN5bmMgZnVuY3Rpb24gdGltZWQ8VD4obmFtZTogc3RyaW5nLCBydW46ICgpID0+IFByb21pc2U8VD4pOiBQcm9taXNlPFQ+IHtcbiAgICAgICAgbGV0IGJlZ2FuID0gRGF0ZS5ub3coKTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJldHVybiBhd2FpdCBydW4oKTtcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgIHRpbWluZ3Muc2V0KG5hbWUsICh0aW1pbmdzLmdldChuYW1lKSB8fCAwKSArIChEYXRlLm5vdygpIC0gYmVnYW4pKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBUaGUgZGlzayBpcyB0aGUgcmVjb3JkOiBhIGJ1Y2tldCBleGlzdHMgaGVyZSB3aGVuIGl0IGhhcyBhdCBsZWFzdCBvbmUgc3RvcmUgZm9sZGVyLCBhbmQgc2V2ZXJhbCBuYW1lcyBmb3Igb25lIGJ1Y2tldCBhcmUgc3RpbGwgb25lIGJ1Y2tldFxuICAgIGxldCBmb2xkZXJzID0gYXdhaXQgdGltZWQoXCJyZWFkZGlyXCIsICgpID0+IGxpc3RBY2NvdW50U3RvcmVGb2xkZXJzKGFjY291bnQpKTtcbiAgICBsZXQgYnlCdWNrZXQgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpO1xuICAgIGZvciAobGV0IHN0b3JlIG9mIGZvbGRlcnMpIHtcbiAgICAgICAgaWYgKGJ5QnVja2V0LmhhcyhzdG9yZS5idWNrZXROYW1lKSkgY29udGludWU7XG4gICAgICAgIGJ5QnVja2V0LnNldChzdG9yZS5idWNrZXROYW1lLCBzdG9yZS5mb2xkZXIpO1xuICAgIH1cbiAgICBsZXQgbmFtZXMgPSBbLi4uYnlCdWNrZXQua2V5cygpXTtcbiAgICB0cnkge1xuICAgICAgICByZXR1cm4gYXdhaXQgUHJvbWlzZS5hbGwobmFtZXMubWFwKGFzeW5jIGJ1Y2tldE5hbWUgPT4ge1xuICAgICAgICAgICAgbGV0IGtleSA9IGAke2FjY291bnR9LyR7YnVja2V0TmFtZX1gO1xuICAgICAgICAgICAgbGV0IGZvbGRlciA9IGJ5QnVja2V0LmdldChidWNrZXROYW1lKSB8fCBcIlwiO1xuICAgICAgICAgICAgbGV0IGJhc2U6IFNlcnZlckJ1Y2tldEluZm8gPSB7IGJ1Y2tldE5hbWUsIGFjdGl2ZTogZmFsc2UsIGZvbGRlciB9O1xuICAgICAgICAgICAgYmFzZS5kaXNrID0gYXdhaXQgdGltZWQoXCJzdGF0ZnNcIiwgKCkgPT4gZ2V0RGlza0luZm8oZm9sZGVyKSkuY2F0Y2goKGU6IEVycm9yKSA9PiB7XG4gICAgICAgICAgICAgICAgYmFzZS5kaXNrRXJyb3IgPSBTdHJpbmcoZS5zdGFjayA/PyBlKS5zbGljZSgwLCA1MDApO1xuICAgICAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGJhc2Uud3JpdGVTdGF0cyA9IGdldEJ1Y2tldFdyaXRlU3RhdHMoa2V5KTtcbiAgICAgICAgICAgIGNvbnN0IGxvYWRlZFByb21pc2UgPSBidWNrZXRzLmdldChrZXkpO1xuICAgICAgICAgICAgaWYgKGxvYWRlZFByb21pc2UpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgbG9hZGVkID0gYXdhaXQgdGltZWQoXCJhd2FpdExvYWRlZFwiLCAoKSA9PiBsb2FkZWRQcm9taXNlKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGxvYWRlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsgLi4uYmFzZSwgYWN0aXZlOiB0cnVlLCBjb25maWc6IGdldEJ1Y2tldENvbmZpZyhsb2FkZWQpIH07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7IC4uLmJhc2UsIGFjdGl2ZTogdHJ1ZSwgZXJyb3I6IFN0cmluZygoZSBhcyBFcnJvcikuc3RhY2sgPz8gZSkuc2xpY2UoMCwgNTAwKSB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgY29uc3QgcGFyc2VkID0gYXdhaXQgdGltZWQoXCJyZWFkUm91dGluZ0ZpbGVcIiwgKCkgPT4gcmVhZFJvdXRpbmdGcm9tRGlzayhhY2NvdW50LCBidWNrZXROYW1lKSk7XG4gICAgICAgICAgICAgICAgaWYgKCFwYXJzZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsgLi4uYmFzZSwgZXJyb3I6IGBObyByb3V0aW5nIGZpbGUgKCR7Uk9VVElOR19GSUxFfSkgaW4gYW55IG9mIGl0cyBzdG9yZXNgIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB7IC4uLmJhc2UsIGNvbmZpZzogeyByZW1vdGVDb25maWc6IHBhcnNlZCB9IH07XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgLi4uYmFzZSwgZXJyb3I6IFN0cmluZygoZSBhcyBFcnJvcikuc3RhY2sgPz8gZSkuc2xpY2UoMCwgNTAwKSB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9KSk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgLy8gVGhlIHBhcnRzIHJ1biBjb25jdXJyZW50bHksIHNvIHRoZXNlIGFyZSBzdW1tZWQgd2FsbCB0aW1lcyBwZXIgcGFydCwgbm90IGEgYnJlYWtkb3duIG9mIHRoZSB0b3RhbFxuICAgICAgICBsZXQgcGFydHMgPSBbLi4udGltaW5nc10ubWFwKChbbmFtZSwgbXNdKSA9PiBgJHtuYW1lfSAke21zfW1zYCkuam9pbihcIiwgXCIpO1xuICAgICAgICBjb25zb2xlLmxvZyhgZGVidWdMaXN0QWNjb3VudEJ1Y2tldHMoJHthY2NvdW50fSkgdG9vayAke0RhdGUubm93KCkgLSBzdGFydH1tcyBmb3IgJHtuYW1lcy5sZW5ndGh9IGJ1Y2tldHM6ICR7cGFydHN9YCk7XG4gICAgfVxufVxuXG5leHBvcnQgdHlwZSBCdWNrZXRXcml0ZVN0YXRzID0ge1xuICAgIC8qKiBFdmVyeSBzZXQgY2FsbCB0aGUgYnVja2V0IGFjY2VwdGVkICovXG4gICAgb3JpZ2luYWxXcml0ZXM6IG51bWJlcjtcbiAgICBvcmlnaW5hbEJ5dGVzOiBudW1iZXI7XG4gICAgLyoqIFdoYXQgYWN0dWFsbHkgcmVhY2hlZCB0aGUgc291cmNlcy4gRmFzdCB3cml0ZXMgY29hbGVzY2UgcmVwZWF0ZWQgd3JpdGVzIHRvIHRoZSBzYW1lIGtleSwgc28gdGhpcyBpcyBsb3dlciB0aGFuIHRoZSBvcmlnaW5hbCBjb3VudHMgKGFuZCBpcyB3aGF0IHRoZSBkaXNrIGFjdHVhbGx5IGRpZCkuICovXG4gICAgZmx1c2hlZFdyaXRlczogbnVtYmVyO1xuICAgIGZsdXNoZWRCeXRlczogbnVtYmVyO1xufTtcbmZ1bmN0aW9uIGVtcHR5V3JpdGVTdGF0cygpOiBCdWNrZXRXcml0ZVN0YXRzIHtcbiAgICByZXR1cm4geyBvcmlnaW5hbFdyaXRlczogMCwgb3JpZ2luYWxCeXRlczogMCwgZmx1c2hlZFdyaXRlczogMCwgZmx1c2hlZEJ5dGVzOiAwIH07XG59XG5cbi8vIEluIG1lbW9yeSBvbmx5OiB0b3RhbHMgc2luY2UgdGhpcyBwcm9jZXNzIHN0YXJ0ZWQgKG9yIHRoZSBsYXN0IGNsZWFyV3JpdGVTdGF0cykuIFBlcnNpc3RpbmcgdGhlbSB0byBkaXNrIHdhcyBtb3JlIG1hY2hpbmVyeSB0aGFuIHRoZSBudW1iZXJzIHdlcmUgd29ydGguXG5jb25zdCB3cml0ZVN0YXRzID0gbmV3IE1hcDxzdHJpbmcsIEJ1Y2tldFdyaXRlU3RhdHM+KCk7XG5cbmZ1bmN0aW9uIGNvdW50QnVja2V0V3JpdGUoa2V5OiBzdHJpbmcsIGtpbmQ6IFwib3JpZ2luYWxcIiB8IFwiZmx1c2hlZFwiLCBieXRlczogbnVtYmVyKTogdm9pZCB7XG4gICAgbGV0IHN0YXRzID0gd3JpdGVTdGF0cy5nZXQoa2V5KTtcbiAgICBpZiAoIXN0YXRzKSB7XG4gICAgICAgIHN0YXRzID0gZW1wdHlXcml0ZVN0YXRzKCk7XG4gICAgICAgIHdyaXRlU3RhdHMuc2V0KGtleSwgc3RhdHMpO1xuICAgIH1cbiAgICBpZiAoa2luZCA9PT0gXCJvcmlnaW5hbFwiKSB7XG4gICAgICAgIHN0YXRzLm9yaWdpbmFsV3JpdGVzKys7XG4gICAgICAgIHN0YXRzLm9yaWdpbmFsQnl0ZXMgKz0gYnl0ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgc3RhdHMuZmx1c2hlZFdyaXRlcysrO1xuICAgICAgICBzdGF0cy5mbHVzaGVkQnl0ZXMgKz0gYnl0ZXM7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBnZXRCdWNrZXRXcml0ZVN0YXRzKGtleTogc3RyaW5nKTogQnVja2V0V3JpdGVTdGF0cyB7XG4gICAgcmV0dXJuIHdyaXRlU3RhdHMuZ2V0KGtleSkgfHwgZW1wdHlXcml0ZVN0YXRzKCk7XG59XG5cbi8qKiBaZXJvZXMgdGhlIHdyaXRlIHN0YXRpc3RpY3Mgb2YgZXZlcnkgYnVja2V0IGluIHRoZSBhY2NvdW50LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlYnVnQ2xlYXJBY2NvdW50V3JpdGVTdGF0cyhhY2NvdW50OiBzdHJpbmcpOiBudW1iZXIge1xuICAgIGxldCBwcmVmaXggPSBgJHthY2NvdW50fS9gO1xuICAgIGxldCBjbGVhcmVkID0gMDtcbiAgICBmb3IgKGxldCBrZXkgb2YgWy4uLndyaXRlU3RhdHMua2V5cygpXSkge1xuICAgICAgICBpZiAoIWtleS5zdGFydHNXaXRoKHByZWZpeCkpIGNvbnRpbnVlO1xuICAgICAgICB3cml0ZVN0YXRzLmRlbGV0ZShrZXkpO1xuICAgICAgICBjbGVhcmVkKys7XG4gICAgfVxuICAgIGNvbnNvbGUubG9nKGBDbGVhcmVkIHRoZSB3cml0ZSBzdGF0aXN0aWNzIG9mICR7Y2xlYXJlZH0gYnVja2V0cyBpbiBhY2NvdW50ICR7YWNjb3VudH1gKTtcbiAgICByZXR1cm4gY2xlYXJlZDtcbn1cbiJdfQ==
|
|
384
|
+
/* _JS_SOURCE_HASH = "9c3ed07e6e3f1b37584736f5f826c4eabe4d4af1f4da123f09030d6271504dd5"; */
|