sliftutils 1.7.89 → 1.7.91

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.
Files changed (41) hide show
  1. package/index.d.ts +36 -81
  2. package/misc/https/dist/cloudflareHelpers.ts.cache +2 -2
  3. package/misc/https/dist/dns.ts.cache +2 -2
  4. package/package.json +1 -1
  5. package/storage/BulkDatabase2/dist/BulkDatabaseBase.ts.cache +2 -2
  6. package/storage/BulkDatabase2/dist/BulkDatabaseFormat.ts.cache +2 -2
  7. package/storage/BulkDatabase2/dist/BulkDatabaseMerge.ts.cache +2 -2
  8. package/storage/BulkDatabase2/dist/LoadedIndex.ts.cache +2 -2
  9. package/storage/BulkDatabase2/dist/WriteOverlay.ts.cache +2 -2
  10. package/storage/BulkDatabase2/dist/blockCache.ts.cache +2 -2
  11. package/storage/BulkDatabase2/dist/mergeLock.ts.cache +2 -2
  12. package/storage/BulkDatabase2/dist/mergeMarkers.ts.cache +2 -2
  13. package/storage/BulkDatabase2/dist/streamLog.ts.cache +2 -2
  14. package/storage/BulkDatabase2/dist/syncClient.ts.cache +2 -2
  15. package/storage/dist/ArchivesDisk.ts.cache +2 -2
  16. package/storage/dist/IArchives.ts.cache +2 -2
  17. package/storage/dist/archiveHelpers.ts.cache +87 -0
  18. package/storage/dist/backblaze.ts.cache +2 -2
  19. package/storage/remoteStorage/accessStats.d.ts +12 -0
  20. package/storage/remoteStorage/accessStats.ts +47 -0
  21. package/storage/remoteStorage/blobStore.d.ts +3 -1
  22. package/storage/remoteStorage/blobStore.ts +5 -0
  23. package/storage/remoteStorage/dist/ArchivesRemote.ts.cache +2 -2
  24. package/storage/remoteStorage/dist/accessStats.ts.cache +42 -3
  25. package/storage/remoteStorage/dist/blobStore.ts.cache +7 -4
  26. package/storage/remoteStorage/dist/createArchives.ts.cache +2 -2
  27. package/storage/remoteStorage/dist/intermediateManagement.ts.cache +56 -50
  28. package/storage/remoteStorage/dist/storageController.ts.cache +47 -58
  29. package/storage/remoteStorage/dist/storageServerState.ts.cache +119 -248
  30. package/storage/remoteStorage/dist/storeConfig.ts.cache +2 -2
  31. package/storage/remoteStorage/dist/storePlan.ts.cache +4 -56
  32. package/storage/remoteStorage/dist/storeSync.ts.cache +6 -5
  33. package/storage/remoteStorage/intermediateManagement.d.ts +2 -3
  34. package/storage/remoteStorage/intermediateManagement.ts +53 -46
  35. package/storage/remoteStorage/storageController.ts +35 -44
  36. package/storage/remoteStorage/storageServerState.d.ts +17 -57
  37. package/storage/remoteStorage/storageServerState.ts +112 -279
  38. package/storage/remoteStorage/storeConfig.d.ts +2 -0
  39. package/storage/remoteStorage/storeConfig.ts +2 -0
  40. package/storage/remoteStorage/storePlan.d.ts +0 -20
  41. package/storage/remoteStorage/storePlan.ts +1 -69
@@ -1,47 +1,86 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
3
- //exports.clearAccountWriteStats = exports.listAccountBuckets = exports.activateBucket = exports.getActiveBucket = exports.getActiveBucketKeys = exports.writeRoutingConfig = exports.reloadBucket = exports.getLoadedBucket = exports.getStore = exports.resolveSourceArchives = exports.getBucketStates = exports.bucketIndexTotals = exports.bucketSyncStatus = exports.getBucketConfig = exports.readBucketInternal = exports.findBucketStore = exports.requireBucket = void 0;
3
+ //exports.debugListAccountBuckets = exports.activateBucket = exports.debugGetActiveBucket = exports.getActiveBucketKeys = exports.writeRoutingConfig = exports.resolveSourceArchives = exports.debugBucketIndexTotals = exports.bucketSyncStatus = exports.getBucketArchivesConfig = exports.readBucketInternal = exports.getBucketStores = exports.findBucketStore = exports.getStore = void 0;
4
4
  const blobStore_1 = require("./blobStore");
5
5
  const remoteConfig_1 = require("./remoteConfig");
6
6
  const storeSources_1 = require("./storeSources");
7
7
  const storageController_1 = require("./storageController");
8
8
  const serverConfig_1 = require("./serverConfig");
9
+ const validation_1 = require("./validation");
9
10
  const bucketDisk_1 = require("./bucketDisk");
10
11
  const intermediateManagement_1 = require("./intermediateManagement");
11
12
  const storePlan_1 = require("./storePlan");
12
- /** 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. */
13
- async function requireBucket(account, bucketName) {
14
- let bucket = await getLoadedBucket(account, bucketName);
15
- if (!bucket) {
16
- throw new Error(`Bucket ${account}/${bucketName} does not exist on this server. Write its routing config to ${JSON.stringify(remoteConfig_1.ROUTING_FILE)} to create it.`);
13
+ const accessStats_1 = require("./accessStats");
14
+ /**
15
+ * What this server HAS: the stores, by name (getStore) - made once, self-configuring from there -
16
+ * and the three entry points a request resolves through (findBucketStore, readBucketInternal,
17
+ * writeRoutingConfig). There is no cached bucket state: a bucket is nothing but the stores whose
18
+ * folders share its name, listed off the disk when something genuinely needs all of them.
19
+ */
20
+ /**
21
+ * Every store this process runs, by folder - which IS the store's identity: account, name, bucket.
22
+ * A store is made once, configures itself from the routing config it holds, and stays; nothing here
23
+ * decides what it is, only that it exists.
24
+ */
25
+ const stores = new Map();
26
+ // The opened stores of each `${account}/${bucketName}`, by name - which buckets are ACTIVE (something touched them), for deploy handoffs and the debug pages. Purely a registry of what getStore already made.
27
+ const activeStores = new Map();
28
+ function getStore(account, bucketName, name) {
29
+ // The one place a name becomes a folder, so the one place it is validated (it can come straight off the wire)
30
+ (0, validation_1.assertValidSourceName)(name);
31
+ let folder = (0, bucketDisk_1.getBucketFolder)(name, account, bucketName);
32
+ let existing = stores.get(folder);
33
+ if (existing)
34
+ return existing;
35
+ console.log(`Opening store ${JSON.stringify(name)} of bucket ${account}/${bucketName} (folder ${folder}) - created on this first use if it never existed`);
36
+ let store = new blobStore_1.BlobStore(folder, name, {
37
+ // Which entries in ITS routing config are this server's copy of it
38
+ isSelf: source => (0, storePlan_1.isSelfSource)(source, account, bucketName),
39
+ createSource: config => (0, storeSources_1.createStoreSource)({ sourceConfig: config.sourceConfig, folder, writeDelay: config.writeDelay }),
40
+ applySource: (source, sourceConfig, writeDelay) => (0, storeSources_1.applySourceConfig)(source, sourceConfig, writeDelay),
41
+ onWriteCounted: (kind, bytes) => (0, accessStats_1.countBucketWrite)(`${account}/${bucketName}`, kind, bytes),
42
+ resolveSourceUrl: resolveSourceArchives,
43
+ // The store is the one that knows when a config landed, and a config with upcoming windows is what boundary scans are armed from
44
+ onRoutingApplied: routing => (0, intermediateManagement_1.scheduleBoundaryWork)(account, bucketName, routing),
45
+ });
46
+ stores.set(folder, store);
47
+ let key = `${account}/${bucketName}`;
48
+ let byName = activeStores.get(key);
49
+ if (!byName) {
50
+ byName = new Map();
51
+ activeStores.set(key, byName);
17
52
  }
18
- return bucket;
53
+ byName.set(name, store);
54
+ // 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
55
+ 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}`); });
56
+ return store;
19
57
  }
20
- exports.requireBucket = requireBucket;
21
- /** The store serving a request: the one the client's selected entry NAMES. Nothing else is compared - not the window, not the route, not the flags - because the name is what says which storage this is, and everything else is policy the store itself applies to the request. A client a config version behind on some flag therefore still reaches the right store, which is the whole point of naming it. */
22
- async function findBucketStore(account, bucketName, sourceConfig) {
23
- let bucket = await requireBucket(account, bucketName);
58
+ exports.getStore = getStore;
59
+ /** 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. */
60
+ function findBucketStore(account, bucketName, sourceConfig) {
24
61
  if (!sourceConfig) {
25
- throw new Error(`No remote source configuration was provided for bucket ${account}/${bucketName}: every request must say which configured source it selected. This server has: ${JSON.stringify(bucket.stores.map(x => x.name))}`);
26
- }
27
- let store = bucket.stores.find(x => x.name === sourceConfig.name);
28
- if (store)
29
- return store;
30
- // The loaded bucket is a snapshot of the disk from when it loaded; a store created since (a new name in a rewritten routing config) is on the disk but not in the snapshot, so a miss re-reads the disk once before it is believed
31
- let previousNames = bucket.stores.map(x => x.name);
32
- let reloaded = await reloadBucket(account, bucketName);
33
- store = reloaded === null || reloaded === void 0 ? void 0 : reloaded.stores.find(x => x.name === sourceConfig.name);
34
- if (store) {
35
- console.log(`Reloaded bucket ${account}/${bucketName} to find store ${JSON.stringify(sourceConfig.name)}: its stores changed from ${JSON.stringify(previousNames)} to ${JSON.stringify(reloaded === null || reloaded === void 0 ? void 0 : reloaded.stores.map(x => x.name))}`);
36
- return store;
62
+ throw new Error(`No remote source configuration was provided for bucket ${account}/${bucketName}: every request must say which configured source it selected`);
37
63
  }
38
- throw new Error(`This server has no store named ${JSON.stringify(sourceConfig.name)} for bucket ${account}/${bucketName} (it has: ${JSON.stringify((reloaded || bucket).stores.map(x => x.name))}). Requested: ${JSON.stringify(sourceConfig)}`);
64
+ return getStore(account, bucketName, sourceConfig.name);
39
65
  }
40
66
  exports.findBucketStore = findBucketStore;
67
+ /** The stores of a bucket as the DISK records them (a bucket is nothing more than the store folders sharing its name), opened - so the ones that weren't running yet start synchronizing. Empty when the bucket does not exist here. */
68
+ async function getBucketStores(account, bucketName) {
69
+ let folders = await (0, bucketDisk_1.listBucketStoreFolders)(account, bucketName);
70
+ return folders.map(x => ({ name: x.name, store: getStore(account, bucketName, x.name) }));
71
+ }
72
+ exports.getBucketStores = getBucketStores;
73
+ async function requireBucketStores(account, bucketName) {
74
+ let list = await getBucketStores(account, bucketName);
75
+ if (!list.length) {
76
+ throw new Error(`Bucket ${account}/${bucketName} does not exist on this server. Write its routing config to ${JSON.stringify(remoteConfig_1.ROUTING_FILE)} to create it.`);
77
+ }
78
+ return list;
79
+ }
41
80
  /** 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. */
42
81
  async function readBucketInternal(account, bucketName, config) {
43
- let bucket = await requireBucket(account, bucketName);
44
- let results = await Promise.all(bucket.stores.map(s => s.store.get2({ path: config.path, range: config.range, includeTombstones: config.includeTombstones, internal: true })));
82
+ let bucketStores = await requireBucketStores(account, bucketName);
83
+ let results = await Promise.all(bucketStores.map(s => s.store.get2({ path: config.path, range: config.range, includeTombstones: config.includeTombstones, internal: true })));
45
84
  let best;
46
85
  for (let result of results) {
47
86
  if (result && (!best || result.writeTime > best.writeTime)) {
@@ -51,13 +90,13 @@ async function readBucketInternal(account, bucketName, config) {
51
90
  return best;
52
91
  }
53
92
  exports.readBucketInternal = readBucketInternal;
54
- function getBucketConfig(bucket) {
93
+ function aggregateArchivesConfig(bucketStores, routing) {
55
94
  let index = { fileCount: 0, byteCount: 0 };
56
95
  let indexSources = [];
57
96
  let syncing = [];
58
97
  let readerDiskLimit;
59
- for (let s of bucket.stores) {
60
- let progress = s.store.getSyncProgress();
98
+ for (let store of bucketStores) {
99
+ let progress = store.getSyncProgress();
61
100
  index.fileCount += progress.index.fileCount;
62
101
  index.byteCount += progress.index.byteCount;
63
102
  indexSources.push(...progress.sources);
@@ -67,16 +106,22 @@ function getBucketConfig(bucket) {
67
106
  return {
68
107
  // Every store is index-backed, so the change feed is always native
69
108
  supportsChangesAfter: true,
70
- remoteConfig: bucket.routing,
109
+ remoteConfig: routing,
71
110
  index,
72
111
  indexSources,
73
112
  readerDiskLimit,
74
113
  syncing,
75
114
  };
76
115
  }
77
- exports.getBucketConfig = getBucketConfig;
78
- async function bucketSyncStatus(bucket) {
79
- let statuses = await Promise.all(bucket.stores.map(s => s.store.getSyncStatus()));
116
+ async function getBucketArchivesConfig(account, bucketName) {
117
+ let bucketStores = await requireBucketStores(account, bucketName);
118
+ let routing = await (0, bucketDisk_1.readRoutingFromDisk)(account, bucketName);
119
+ return aggregateArchivesConfig(bucketStores.map(x => x.store), routing);
120
+ }
121
+ exports.getBucketArchivesConfig = getBucketArchivesConfig;
122
+ async function bucketSyncStatus(account, bucketName) {
123
+ let bucketStores = await requireBucketStores(account, bucketName);
124
+ let statuses = await Promise.all(bucketStores.map(s => s.store.getSyncStatus()));
80
125
  return {
81
126
  allScansComplete: statuses.every(x => x.allScansComplete),
82
127
  indexSize: statuses.reduce((sum, x) => sum + x.indexSize, 0),
@@ -84,23 +129,16 @@ async function bucketSyncStatus(bucket) {
84
129
  };
85
130
  }
86
131
  exports.bucketSyncStatus = bucketSyncStatus;
87
- async function bucketIndexTotals(bucket) {
88
- let totals = await Promise.all(bucket.stores.map(s => s.store.computeIndexTotals()));
132
+ async function debugBucketIndexTotals(account, bucketName) {
133
+ let bucketStores = await requireBucketStores(account, bucketName);
134
+ let totals = await Promise.all(bucketStores.map(s => s.store.computeIndexTotals()));
89
135
  return {
90
136
  fileCount: totals.reduce((sum, x) => sum + x.fileCount, 0),
91
137
  byteCount: totals.reduce((sum, x) => sum + x.byteCount, 0),
92
138
  sources: totals.flatMap(x => x.sources),
93
139
  };
94
140
  }
95
- exports.bucketIndexTotals = bucketIndexTotals;
96
- const buckets = new Map();
97
- // The resolved ones, for the code that walks buckets rather than asking for one (see getBucketStates)
98
- const loadedBuckets = new Map();
99
- /** 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. */
100
- function getBucketStates() {
101
- return [...loadedBuckets.values()];
102
- }
103
- exports.getBucketStates = getBucketStates;
141
+ exports.debugBucketIndexTotals = debugBucketIndexTotals;
104
142
  const resolvedSourceArchives = new Map();
105
143
  /** 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. */
106
144
  function resolveSourceArchives(url) {
@@ -117,87 +155,6 @@ function resolveSourceArchives(url) {
117
155
  return archives;
118
156
  }
119
157
  exports.resolveSourceArchives = resolveSourceArchives;
120
- /** 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. */
121
- function sourcePersistentUrl(sourceConfig, folder) {
122
- if (!sourceConfig)
123
- return folder;
124
- return sourceConfig.intermediate || sourceConfig.url;
125
- }
126
- /** 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. */
127
- /**
128
- * Every store this process runs, by folder - which IS the store's identity: account, name, bucket.
129
- * A store is made once, configures itself from the routing config it holds, and stays; nothing here
130
- * decides what it is, only that it exists.
131
- */
132
- const stores = new Map();
133
- function getStore(account, bucketName, name) {
134
- let folder = (0, bucketDisk_1.getBucketFolder)(name, account, bucketName);
135
- let existing = stores.get(folder);
136
- if (existing)
137
- return existing;
138
- let store = new blobStore_1.BlobStore(folder, name, {
139
- // Which entries in ITS routing config are this server's copy of it
140
- isSelf: source => (0, storePlan_1.isSelfSource)(source, account, bucketName),
141
- createSource: config => (0, storeSources_1.createStoreSource)({ sourceConfig: config.sourceConfig, folder, writeDelay: config.writeDelay }),
142
- applySource: (source, sourceConfig, writeDelay) => (0, storeSources_1.applySourceConfig)(source, sourceConfig, writeDelay),
143
- onWriteCounted: (kind, bytes) => countBucketWrite(`${account}/${bucketName}`, kind, bytes),
144
- resolveSourceUrl: resolveSourceArchives,
145
- });
146
- stores.set(folder, store);
147
- // 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
148
- 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}`); });
149
- return store;
150
- }
151
- exports.getStore = getStore;
152
- /** 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. */
153
- function buildBucket(account, bucketName, names, routing) {
154
- let plan = routing && (0, storePlan_1.planSelfStores)(account, bucketName, routing) || undefined;
155
- let entriesByName = new Map();
156
- for (let selfStore of (plan === null || plan === void 0 ? void 0 : plan.stores) || []) {
157
- entriesByName.set(selfStore.name, selfStore.entries);
158
- }
159
- // Each store reads its own copy of the config and decides what it is - see BlobStore.applyRoutingConfig. Nothing here configures anything.
160
- let stores = names.map(name => ({
161
- name,
162
- entries: entriesByName.get(name) || [],
163
- folder: (0, bucketDisk_1.getBucketFolder)(name, account, bucketName),
164
- store: getStore(account, bucketName, name),
165
- }));
166
- 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 };
167
- loadedBuckets.set(`${account}/${bucketName}`, loaded);
168
- (0, intermediateManagement_1.scheduleBoundaryWork)(loaded);
169
- return loaded;
170
- }
171
- // 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.
172
- async function loadBucket(account, bucketName) {
173
- let folders = await (0, bucketDisk_1.listBucketStoreFolders)(account, bucketName);
174
- if (!folders.length)
175
- return undefined;
176
- let routing = await (0, bucketDisk_1.readRoutingFromDisk)(account, bucketName);
177
- return buildBucket(account, bucketName, folders.map(x => x.name), routing);
178
- }
179
- function getLoadedBucket(account, bucketName) {
180
- let key = `${account}/${bucketName}`;
181
- return buckets.get(key) || reloadBucket(account, bucketName);
182
- }
183
- exports.getLoadedBucket = getLoadedBucket;
184
- /** 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. */
185
- async function reloadBucket(account, bucketName) {
186
- let key = `${account}/${bucketName}`;
187
- let loaded = loadBucket(account, bucketName);
188
- buckets.set(key, loaded);
189
- void loaded.then(bucket => {
190
- if (!bucket && buckets.get(key) === loaded) {
191
- buckets.delete(key);
192
- }
193
- }, () => {
194
- if (buckets.get(key) === loaded) {
195
- buckets.delete(key);
196
- }
197
- });
198
- return await loaded;
199
- }
200
- exports.reloadBucket = reloadBucket;
201
158
  /**
202
159
  * Writing the routing config is a write like any other: it goes into a store, and the store applies
203
160
  * it to itself and lets its peers pull it. The only thing that happens here is picking WHICH store,
@@ -208,97 +165,58 @@ exports.reloadBucket = reloadBucket;
208
165
  * cancel it mid-flight.
209
166
  */
210
167
  async function writeRoutingConfig(account, bucketName, name, data, config) {
211
- var _a;
212
168
  (0, serverConfig_1.assertWritesAllowed)();
213
169
  let store = getStore(account, bucketName, name);
214
170
  let incoming = (0, remoteConfig_1.parseRoutingData)(data);
215
- let current = (_a = (await getLoadedBucket(account, bucketName))) === null || _a === void 0 ? void 0 : _a.routing;
171
+ let current = await (0, bucketDisk_1.readRoutingFromDisk)(account, bucketName);
216
172
  let stored = (0, intermediateManagement_1.reinjectIntermediates)(current, incoming);
217
173
  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 });
218
- // 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
219
- await reloadBucket(account, bucketName);
220
174
  (0, storageController_1.broadcastRoutingChanged)();
221
175
  }
222
176
  exports.writeRoutingConfig = writeRoutingConfig;
223
- /** 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. */
177
+ /** Which buckets this process currently has active (some store of theirs was opened) - what a deploy successor asks its predecessor for, so it activates exactly the buckets that are actually in use. */
224
178
  function getActiveBucketKeys() {
225
- return [...buckets.keys()].map(key => {
179
+ return [...activeStores.keys()].map(key => {
226
180
  let slash = key.indexOf("/");
227
181
  return { account: key.slice(0, slash), bucketName: key.slice(slash + 1) };
228
182
  });
229
183
  }
230
184
  exports.getActiveBucketKeys = getActiveBucketKeys;
231
- function toActiveBucketInfo(loaded) {
232
- var _a;
233
- return {
234
- // One of its stores' folders - a bucket no longer has a folder of its own, it has one per store
235
- folder: ((_a = loaded.stores[0]) === null || _a === void 0 ? void 0 : _a.folder) || "",
236
- routing: loaded.routing,
237
- selfEntries: loaded.selfEntries,
238
- self: loaded.self,
239
- config: getBucketConfig(loaded),
240
- };
241
- }
242
- /** 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. */
243
- async function getActiveBucket(account, bucketName) {
244
- var _a;
185
+ /** The state of ONE active bucket. Returns an error string when the bucket is not active here, which is the normal state for a bucket nothing has accessed since startup. */
186
+ async function debugGetActiveBucket(account, bucketName) {
245
187
  let key = `${account}/${bucketName}`;
246
- let loadedPromise = buckets.get(key);
247
- if (!loadedPromise) {
248
- return `Bucket ${key} is not loaded on this server, so it has no live state (it loads on first access)`;
188
+ let opened = activeStores.get(key);
189
+ if (!opened || !opened.size) {
190
+ return `Bucket ${key} is not active on this server (a bucket activates on first access)`;
249
191
  }
250
- let loaded;
251
- try {
252
- loaded = await loadedPromise;
253
- }
254
- catch (e) {
255
- return `Bucket ${key} failed to load on this server: ${String((_a = e.stack) !== null && _a !== void 0 ? _a : e).slice(0, 500)}`;
256
- }
257
- if (!loaded) {
258
- return `Bucket ${key} does not exist on this server`;
259
- }
260
- return toActiveBucketInfo(loaded);
192
+ let bucketStores = [...opened.values()];
193
+ let routing = await (0, bucketDisk_1.readRoutingFromDisk)(account, bucketName);
194
+ return { folder: bucketStores[0].folder, routing, config: aggregateArchivesConfig(bucketStores, routing) };
261
195
  }
262
- exports.getActiveBucket = getActiveBucket;
263
- /** 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. */
196
+ exports.debugGetActiveBucket = debugGetActiveBucket;
197
+ /** Loads every store of a bucket that exists on this server's disk into memory, which starts their synchronization and window timers, and returns the bucket's 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-active buckets just return their state. */
264
198
  async function activateBucket(account, bucketName) {
265
- var _a;
266
199
  let key = `${account}/${bucketName}`;
267
- let wasLoaded = buckets.has(key);
268
- let loaded;
269
- try {
270
- loaded = await getLoadedBucket(account, bucketName);
271
- }
272
- catch (e) {
273
- return `Bucket ${key} failed to load on this server: ${String((_a = e.stack) !== null && _a !== void 0 ? _a : e).slice(0, 500)}`;
274
- }
275
- if (!loaded) {
200
+ let wasActive = activeStores.has(key);
201
+ let bucketStores = await getBucketStores(account, bucketName);
202
+ if (!bucketStores.length) {
276
203
  return `Bucket ${key} does not exist on this server (it has no store folders under ${(0, bucketDisk_1.getBucketFolder)("<name>", account, bucketName)})`;
277
204
  }
278
205
  // 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.
279
- for (let s of loaded.stores) {
206
+ for (let s of bucketStores) {
280
207
  await s.store.init();
281
208
  }
282
- if (!wasLoaded) {
283
- console.log(`Activated bucket ${key} on request: it is now loaded and synchronizing`);
209
+ if (!wasActive) {
210
+ console.log(`Activated bucket ${key} on request: its ${bucketStores.length} store(s) are now loaded and synchronizing`);
284
211
  }
285
- return toActiveBucketInfo(loaded);
212
+ let routing = await (0, bucketDisk_1.readRoutingFromDisk)(account, bucketName);
213
+ return { folder: bucketStores[0].store.folder, routing, config: aggregateArchivesConfig(bucketStores.map(x => x.store), routing) };
286
214
  }
287
215
  exports.activateBucket = activateBucket;
288
- async function listAccountBuckets(account) {
216
+ async function debugListAccountBuckets(account) {
289
217
  let start = Date.now();
290
- let timings = new Map();
291
- async function timed(name, run) {
292
- let began = Date.now();
293
- try {
294
- return await run();
295
- }
296
- finally {
297
- timings.set(name, (timings.get(name) || 0) + (Date.now() - began));
298
- }
299
- }
300
218
  // 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
301
- let folders = await timed("readdir", () => (0, bucketDisk_1.listAccountStoreFolders)(account));
219
+ let folders = await (0, bucketDisk_1.listAccountStoreFolders)(account);
302
220
  let byBucket = new Map();
303
221
  for (let store of folders) {
304
222
  if (byBucket.has(store.bucketName))
@@ -311,31 +229,23 @@ async function listAccountBuckets(account) {
311
229
  var _a, _b;
312
230
  let key = `${account}/${bucketName}`;
313
231
  let folder = byBucket.get(bucketName) || "";
314
- let base = { bucketName, active: false, folder };
315
- base.disk = await timed("statfs", () => (0, bucketDisk_1.getDiskInfo)(folder)).catch((e) => {
232
+ let base = { bucketName, active: activeStores.has(key), folder };
233
+ base.disk = await (0, bucketDisk_1.getDiskInfo)(folder).catch((e) => {
316
234
  var _a;
317
235
  base.diskError = String((_a = e.stack) !== null && _a !== void 0 ? _a : e).slice(0, 500);
318
236
  return undefined;
319
237
  });
320
- base.writeStats = getBucketWriteStats(key);
321
- const loadedPromise = buckets.get(key);
322
- if (loadedPromise) {
323
- try {
324
- let loaded = await timed("awaitLoaded", () => loadedPromise);
325
- if (loaded) {
326
- return { ...base, active: true, config: getBucketConfig(loaded) };
327
- }
328
- }
329
- catch (e) {
330
- return { ...base, active: true, error: String((_a = e.stack) !== null && _a !== void 0 ? _a : e).slice(0, 500) };
331
- }
332
- }
238
+ base.writeStats = (0, accessStats_1.getBucketWriteStats)(key);
333
239
  try {
334
- const parsed = await timed("readRoutingFile", () => (0, bucketDisk_1.readRoutingFromDisk)(account, bucketName));
335
- if (!parsed) {
240
+ let routing = await (0, bucketDisk_1.readRoutingFromDisk)(account, bucketName);
241
+ if (base.active) {
242
+ let opened = [...(((_a = activeStores.get(key)) === null || _a === void 0 ? void 0 : _a.values()) || [])];
243
+ return { ...base, config: aggregateArchivesConfig(opened, routing) };
244
+ }
245
+ if (!routing) {
336
246
  return { ...base, error: `No routing file (${remoteConfig_1.ROUTING_FILE}) in any of its stores` };
337
247
  }
338
- return { ...base, config: { remoteConfig: parsed } };
248
+ return { ...base, config: { remoteConfig: routing } };
339
249
  }
340
250
  catch (e) {
341
251
  return { ...base, error: String((_b = e.stack) !== null && _b !== void 0 ? _b : e).slice(0, 500) };
@@ -343,48 +253,9 @@ async function listAccountBuckets(account) {
343
253
  }));
344
254
  }
345
255
  finally {
346
- // The parts run concurrently, so these are summed wall times per part, not a breakdown of the total
347
- let parts = [...timings].map(([name, ms]) => `${name} ${ms}ms`).join(", ");
348
- console.log(`listAccountBuckets(${account}) took ${Date.now() - start}ms for ${names.length} buckets: ${parts}`);
349
- }
350
- }
351
- exports.listAccountBuckets = listAccountBuckets;
352
- function emptyWriteStats() {
353
- return { originalWrites: 0, originalBytes: 0, flushedWrites: 0, flushedBytes: 0 };
354
- }
355
- // In memory only: totals since this process started (or the last clearWriteStats). Persisting them to disk was more machinery than the numbers were worth.
356
- const writeStats = new Map();
357
- function countBucketWrite(key, kind, bytes) {
358
- let stats = writeStats.get(key);
359
- if (!stats) {
360
- stats = emptyWriteStats();
361
- writeStats.set(key, stats);
362
- }
363
- if (kind === "original") {
364
- stats.originalWrites++;
365
- stats.originalBytes += bytes;
366
- }
367
- else {
368
- stats.flushedWrites++;
369
- stats.flushedBytes += bytes;
370
- }
371
- }
372
- function getBucketWriteStats(key) {
373
- return writeStats.get(key) || emptyWriteStats();
374
- }
375
- /** Zeroes the write statistics of every bucket in the account. */
376
- function clearAccountWriteStats(account) {
377
- let prefix = `${account}/`;
378
- let cleared = 0;
379
- for (let key of [...writeStats.keys()]) {
380
- if (!key.startsWith(prefix))
381
- continue;
382
- writeStats.delete(key);
383
- cleared++;
256
+ console.log(`debugListAccountBuckets(${account}) took ${Date.now() - start}ms for ${names.length} buckets`);
384
257
  }
385
- console.log(`Cleared the write statistics of ${cleared} buckets in account ${account}`);
386
- return cleared;
387
258
  }
388
- exports.clearAccountWriteStats = clearAccountWriteStats;
389
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmFnZVNlcnZlclN0YXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3RvcmFnZVNlcnZlclN0YXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUVBLDJDQUF3QztBQUl4QyxpREFBd0c7QUFDeEcsaURBQXNFO0FBQ3RFLDJEQUE4RDtBQUM5RCxpREFBNkU7QUFDN0UsNkNBQWtKO0FBQ2xKLHFFQUF1RjtBQUN2RiwyQ0FBd0U7QUFrQ3hFLDBNQUEwTTtBQUNuTSxLQUFLLFVBQVUsYUFBYSxDQUFDLE9BQWUsRUFBRSxVQUFrQjtJQUNuRSxJQUFJLE1BQU0sR0FBRyxNQUFNLGVBQWUsQ0FBQyxPQUFPLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFDeEQsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ1YsTUFBTSxJQUFJLEtBQUssQ0FBQyxVQUFVLE9BQU8sSUFBSSxVQUFVLCtEQUErRCxJQUFJLENBQUMsU0FBUyxDQUFDLDJCQUFZLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUNoSyxDQUFDO0lBQ0QsT0FBTyxNQUFNLENBQUM7QUFDbEIsQ0FBQztBQU5ELHNDQU1DO0FBRUQsa1pBQWtaO0FBQzNZLEtBQUssVUFBVSxlQUFlLENBQUMsT0FBZSxFQUFFLFVBQWtCLEVBQUUsWUFBc0M7SUFDN0csSUFBSSxNQUFNLEdBQUcsTUFBTSxhQUFhLENBQUMsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDO0lBQ3RELElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNoQixNQUFNLElBQUksS0FBSyxDQUFDLDBEQUEwRCxPQUFPLElBQUksVUFBVSxrRkFBa0YsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN2TyxDQUFDO0lBQ0QsSUFBSSxLQUFLLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJ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O0lBQ0QsSUFBSSxJQUFJLEtBQUssVUFBVSxFQUFFLENBQUM7UUFDdEIsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3ZCLEtBQUssQ0FBQyxhQUFhLElBQUksS0FBSyxDQUFDO0lBQ2pDLENBQUM7U0FBTSxDQUFDO1FBQ0osS0FBSyxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ3RCLEtBQUssQ0FBQyxZQUFZLElBQUksS0FBSyxDQUFDO0lBQ2hDLENBQUM7QUFDTCxDQUFDO0FBRUQsU0FBUyxtQkFBbUIsQ0FBQyxHQUFXO0lBQ3BDLE9BQU8sVUFBVSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxlQUFlLEVBQUUsQ0FBQztBQUNwRCxDQUFDO0FBRUQsa0VBQWtFO0FBQ2xFLFNBQWdCLHNCQUFzQixDQUFDLE9BQWU7SUFDbEQsSUFBSSxNQUFNLEdBQUcsR0FBRyxPQUFPLEdBQUcsQ0FBQztJQUMzQixJQUFJLE9BQU8sR0FBRyxDQUFDLENBQUM7SUFDaEIsS0FBSyxJQUFJLEdBQUcsSUFBSSxDQUFDLEdBQUcsVUFBVSxDQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsQ0FBQztRQUNyQyxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUM7WUFBRSxTQUFTO1FBQ3RDLFVBQVUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDdkIsT0FBTyxFQUFFLENBQUM7SUFDZCxDQUFDO0lBQ0QsT0FBTyxDQUFDLEdBQUcsQ0FBQyxtQ0FBbUMsT0FBTyx1QkFBdUIsT0FBTyxFQUFFLENBQUMsQ0FBQztJQUN4RixPQUFPLE9BQU8sQ0FBQztBQUNuQixDQUFDO0FBVkQsd0RBVUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgcGF0aCBmcm9tIFwicGF0aFwiO1xuaW1wb3J0IGZzIGZyb20gXCJmc1wiO1xuaW1wb3J0IHsgQmxvYlN0b3JlIH0gZnJvbSBcIi4vYmxvYlN0b3JlXCI7XG5pbXBvcnQge1xuICAgIFJlbW90ZUNvbmZpZywgSG9zdGVkQ29uZmlnLCBTb3VyY2VDb25maWcsIElBcmNoaXZlcywgQXJjaGl2ZXNDb25maWcsIEFyY2hpdmVzU3luY1N0YXR1cywgU3luY0FjdGl2aXR5LFxufSBmcm9tIFwiLi4vSUFyY2hpdmVzXCI7XG5pbXBvcnQgeyBST1VUSU5HX0ZJTEUsIHBhcnNlUm91dGluZ0RhdGEsIHNlcmlhbGl6ZVJlbW90ZUNvbmZpZywgbm9ybWFsaXplU291cmNlIH0gZnJvbSBcIi4vcmVtb3RlQ29uZmlnXCI7XG5pbXBvcnQgeyBjcmVhdGVTdG9yZVNvdXJjZSwgYXBwbHlTb3VyY2VDb25maWcgfSBmcm9tIFwiLi9zdG9yZVNvdXJjZXNcIjtcbmltcG9ydCB7IGJyb2FkY2FzdFJvdXRpbmdDaGFuZ2VkIH0gZnJvbSBcIi4vc3RvcmFnZUNvbnRyb2xsZXJcIjtcbmltcG9ydCB7IGdldFN0b3JhZ2VTZXJ2ZXJDb25maWcsIGFzc2VydFdyaXRlc0FsbG93ZWQgfSBmcm9tIFwiLi9zZXJ2ZXJDb25maWdcIjtcbmltcG9ydCB7IGdldEJ1Y2tldEZvbGRlciwgbGlzdEFjY291bnRTdG9yZUZvbGRlcnMsIGxpc3RCdWNrZXRTdG9yZUZvbGRlcnMsIHJlYWRSb3V0aW5nRnJvbURpc2ssIGdldERpc2tJbmZvLCBCdWNrZXREaXNrSW5mbyB9IGZyb20gXCIuL2J1Y2tldERpc2tcIjtcbmltcG9ydCB7IHNjaGVkdWxlQm91bmRhcnlXb3JrLCByZWluamVjdEludGVybWVkaWF0ZXMgfSBmcm9tIFwiLi9pbnRlcm1lZGlhdGVNYW5hZ2VtZW50XCI7XG5pbXBvcnQgeyBwbGFuU2VsZlN0b3JlcywgaXNTZWxmU291cmNlLCBTZWxmU3VtbWFyeSB9IGZyb20gXCIuL3N0b3JlUGxhblwiO1xuXG4vKipcbiAqIFdoYXQgdGhpcyBzZXJ2ZXIgSEFTLCBhcyBvcHBvc2VkIHRvIHdoYXQgYW55IG9mIGl0IGRvZXMuIEZvdXIgdGhpbmdzLCBhbmQgbm90aGluZyBlbHNlOlxuICpcbiAqIC0gdGhlIHN0b3JlcywgYnkgZm9sZGVyIChnZXRTdG9yZSkgLSBtYWRlIG9uY2UsIGFuZCBzZWxmLWNvbmZpZ3VyaW5nIGZyb20gdGhlcmVcbiAqIC0gd2hpY2ggb2YgdGhlbSBhIHJlcXVlc3QgbWVhbnMgKGZpbmRCdWNrZXRTdG9yZSksIHdoaWNoIGlzIG9ubHkgZXZlciBhIG5hbWVcbiAqIC0gd2hhdCBleGlzdHMgb24gZGlzaywgZm9yIGxpc3RpbmdzIGFuZCBmb3IgdGhlIHBhZ2VzIHRoYXQgcmVwb3J0IGl0XG4gKlxuICogSXQgZGVjaWRlcyBub3RoaW5nIGFib3V0IHJvdXRlcywgd2luZG93cyBvciBwZWVycyAtIGEgc3RvcmUgcmVhZHMgaXRzIG93biBjb25maWcgYW5kIHdvcmtzIHRoYXRcbiAqIG91dCBpdHNlbGYgKEJsb2JTdG9yZS5hcHBseVJvdXRpbmdDb25maWcpIC0gYW5kIGl0IHNjaGVkdWxlcyBub3RoaW5nOiBzd2l0Y2hvdmVycyBhbmQgdGhlIGhhbmRvdmVyc1xuICogdGhleSBjYXVzZSBsaXZlIGluIGludGVybWVkaWF0ZU1hbmFnZW1lbnQuXG4gKi9cblxuZXhwb3J0IHR5cGUgTG9hZGVkU3RvcmUgPSB7XG4gICAgLy8gVGhlIG5hbWUgaXRzIGVudHJpZXMgZ2F2ZSBpdCAoc2VlIENvbW1vbkNvbmZpZy5uYW1lKSAtIGl0cyBpZGVudGl0eSBoZXJlLCBpdHMgZm9sZGVyIG9uIGRpc2ssIGFuZCBob3cgYSByZXF1ZXN0IGZpbmRzIGl0XG4gICAgbmFtZTogc3RyaW5nO1xuICAgIC8vIFRoZSBleGFjdCBzZWxmIGVudHJpZXMgdGhpcyBzdG9yZSBzZXJ2ZXMgKHNhbWUgcm91dGUsIGRpZmZlcmVudCB2YWxpZCB3aW5kb3dzKS4gRW1wdHkgd2hlbiB3ZSBhcmUgbm90IGluIHRoZSBjb25maWcgYnV0IHN0aWxsIHNlcnZlIG91ciBkaXNrIGRhdGEuXG4gICAgZW50cmllczogSG9zdGVkQ29uZmlnW107XG4gICAgZm9sZGVyOiBzdHJpbmc7XG4gICAgc3RvcmU6IEJsb2JTdG9yZTtcbn07XG5cbi8vIEEgYnVja2V0IGxvYWRlZCBvbiB0aGlzIHNlcnZlcjogdGhlIHN0b3JlcyBpdCBoYXMgaGVyZSwgYW5kIHdoYXQgdGhlIG5ld2VzdCBvZiB0aGVpciBjb25maWdzIHNheXMgYWJvdXQgdXMuIFB1cmUgZGF0YSAtIHRoZSBzdG9yZXMgdGhlbXNlbHZlcyBkbyB0aGUgd29yaywgaW5jbHVkaW5nIGNvbmZpZ3VyaW5nIHRoZW1zZWx2ZXMuXG5leHBvcnQgdHlwZSBCdWNrZXRTdGF0ZSA9IHtcbiAgICBhY2NvdW50OiBzdHJpbmc7XG4gICAgYnVja2V0TmFtZTogc3RyaW5nO1xuICAgIC8vIFRoZSBuZXdlc3Qgcm91dGluZyBjb25maWcgYW1vbmcgaXRzIHN0b3Jlcywgb3IgYWJzZW50IHdoZW4gbm9uZSBvZiB0aGVtIGhhcyBvbmUgeWV0XG4gICAgcm91dGluZz86IFJlbW90ZUNvbmZpZztcbiAgICBzZWxmRW50cmllczogSG9zdGVkQ29uZmlnW107XG4gICAgc2VsZjogU2VsZlN1bW1hcnkgfCB1bmRlZmluZWQ7XG4gICAgc3RvcmVzOiBMb2FkZWRTdG9yZVtdO1xufTtcblxuLyoqIFRoZSBsb2FkZWQgYnVja2V0LCBsb2FkaW5nIGl0ICh3aGljaCBpbnN0YW50aWF0ZXMgaXRzIHN0b3JlcyBhbmQgc3RhcnRzIHRoZWlyIHN5bmNocm9uaXphdGlvbikgaWYgbmVlZGVkLiBBIGJ1Y2tldCB0aGF0IGRvZXMgbm90IGV4aXN0IG9uIHRoaXMgc2VydmVyIHRocm93cyAtIGNhbGxlcnMgbmV2ZXIgc2VlIHVuZGVmaW5lZCBidWNrZXRzLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlcXVpcmVCdWNrZXQoYWNjb3VudDogc3RyaW5nLCBidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPEJ1Y2tldFN0YXRlPiB7XG4gICAgbGV0IGJ1Y2tldCA9IGF3YWl0IGdldExvYWRlZEJ1Y2tldChhY2NvdW50LCBidWNrZXROYW1lKTtcbiAgICBpZiAoIWJ1Y2tldCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEJ1Y2tldCAke2FjY291bnR9LyR7YnVja2V0TmFtZX0gZG9lcyBub3QgZXhpc3Qgb24gdGhpcyBzZXJ2ZXIuIFdyaXRlIGl0cyByb3V0aW5nIGNvbmZpZyB0byAke0pTT04uc3RyaW5naWZ5KFJPVVRJTkdfRklMRSl9IHRvIGNyZWF0ZSBpdC5gKTtcbiAgICB9XG4gICAgcmV0dXJuIGJ1Y2tldDtcbn1cblxuLyoqIFRoZSBzdG9yZSBzZXJ2aW5nIGEgcmVxdWVzdDogdGhlIG9uZSB0aGUgY2xpZW50J3Mgc2VsZWN0ZWQgZW50cnkgTkFNRVMuIE5vdGhpbmcgZWxzZSBpcyBjb21wYXJlZCAtIG5vdCB0aGUgd2luZG93LCBub3QgdGhlIHJvdXRlLCBub3QgdGhlIGZsYWdzIC0gYmVjYXVzZSB0aGUgbmFtZSBpcyB3aGF0IHNheXMgd2hpY2ggc3RvcmFnZSB0aGlzIGlzLCBhbmQgZXZlcnl0aGluZyBlbHNlIGlzIHBvbGljeSB0aGUgc3RvcmUgaXRzZWxmIGFwcGxpZXMgdG8gdGhlIHJlcXVlc3QuIEEgY2xpZW50IGEgY29uZmlnIHZlcnNpb24gYmVoaW5kIG9uIHNvbWUgZmxhZyB0aGVyZWZvcmUgc3RpbGwgcmVhY2hlcyB0aGUgcmlnaHQgc3RvcmUsIHdoaWNoIGlzIHRoZSB3aG9sZSBwb2ludCBvZiBuYW1pbmcgaXQuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZmluZEJ1Y2tldFN0b3JlKGFjY291bnQ6IHN0cmluZywgYnVja2V0TmFtZTogc3RyaW5nLCBzb3VyY2VDb25maWc6IFNvdXJjZUNvbmZpZyB8IHVuZGVmaW5lZCk6IFByb21pc2U8TG9hZGVkU3RvcmU+IHtcbiAgICBsZXQgYnVja2V0ID0gYXdhaXQgcmVxdWlyZUJ1Y2tldChhY2NvdW50LCBidWNrZXROYW1lKTtcbiAgICBpZiAoIXNvdXJjZUNvbmZpZykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIHJlbW90ZSBzb3VyY2UgY29uZmlndXJhdGlvbiB3YXMgcHJvdmlkZWQgZm9yIGJ1Y2tldCAke2FjY291bnR9LyR7YnVja2V0TmFtZX06IGV2ZXJ5IHJlcXVlc3QgbXVzdCBzYXkgd2hpY2ggY29uZmlndXJlZCBzb3VyY2UgaXQgc2VsZWN0ZWQuIFRoaXMgc2VydmVyIGhhczogJHtKU09OLnN0cmluZ2lmeShidWNrZXQuc3RvcmVzLm1hcCh4ID0+IHgubmFtZSkpfWApO1xuICAgIH1cbiAgICBsZXQgc3RvcmUgPSBidWNrZXQuc3RvcmVzLmZpbmQoeCA9PiB4Lm5hbWUgPT09IHNvdXJjZUNvbmZpZy5uYW1lKTtcbiAgICBpZiAoc3RvcmUpIHJldHVybiBzdG9yZTtcbiAgICAvLyBUaGUgbG9hZGVkIGJ1Y2tldCBpcyBhIHNuYXBzaG90IG9mIHRoZSBkaXNrIGZyb20gd2hlbiBpdCBsb2FkZWQ7IGEgc3RvcmUgY3JlYXRlZCBzaW5jZSAoYSBuZXcgbmFtZSBpbiBhIHJld3JpdHRlbiByb3V0aW5nIGNvbmZpZykgaXMgb24gdGhlIGRpc2sgYnV0IG5vdCBpbiB0aGUgc25hcHNob3QsIHNvIGEgbWlzcyByZS1yZWFkcyB0aGUgZGlzayBvbmNlIGJlZm9yZSBpdCBpcyBiZWxpZXZlZFxuICAgIGxldCBwcmV2aW91c05hbWVzID0gYnVja2V0LnN0b3Jlcy5tYXAoeCA9PiB4Lm5hbWUpO1xuICAgIGxldCByZWxvYWRlZCA9IGF3YWl0IHJlbG9hZEJ1Y2tldChhY2NvdW50LCBidWNrZXROYW1lKTtcbiAgICBzdG9yZSA9IHJlbG9hZGVkPy5zdG9yZXMuZmluZCh4ID0+IHgubmFtZSA9PT0gc291cmNlQ29uZmlnLm5hbWUpO1xuICAgIGlmIChzdG9yZSkge1xuICAgICAgICBjb25zb2xlLmxvZyhgUmVsb2FkZWQgYnVja2V0ICR7YWNjb3VudH0vJHtidWNrZXROYW1lfSB0byBmaW5kIHN0b3JlICR7SlNPTi5zdHJpbmdpZnkoc291cmNlQ29uZmlnLm5hbWUpfTogaXRzIHN0b3JlcyBjaGFuZ2VkIGZyb20gJHtKU09OLnN0cmluZ2lmeShwcmV2aW91c05hbWVzKX0gdG8gJHtKU09OLnN0cmluZ2lmeShyZWxvYWRlZD8uc3RvcmVzLm1hcCh4ID0+IHgubmFtZSkpfWApO1xuICAgICAgICByZXR1cm4gc3RvcmU7XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcihgVGhpcyBzZXJ2ZXIgaGFzIG5vIHN0b3JlIG5hbWVkICR7SlNPTi5zdHJpbmdpZnkoc291cmNlQ29uZmlnLm5hbWUpfSBmb3IgYnVja2V0ICR7YWNjb3VudH0vJHtidWNrZXROYW1lfSAoaXQgaGFzOiAke0pTT04uc3RyaW5naWZ5KChyZWxvYWRlZCB8fCBidWNrZXQpLnN0b3Jlcy5tYXAoeCA9PiB4Lm5hbWUpKX0pLiBSZXF1ZXN0ZWQ6ICR7SlNPTi5zdHJpbmdpZnkoc291cmNlQ29uZmlnKX1gKTtcbn1cblxuLyoqIEludGVybmFsIChzdG9yZS10by1zdG9yZSkgcmVhZHMgc2tpcCBzdG9yZSBzZWxlY3Rpb24gZW50aXJlbHk6IHRoZSBjYWxsZXIgaXMgYW5vdGhlciBzdG9yZSB3aG9zZSBpbmRleCBzYXlzIHRoaXMgTUFDSElORSBob2xkcyB0aGUgYnl0ZXMgLSB0aGUgcGVyc2lzdGVkIGhvbGRlciBpZGVudGl0eSBpcyBqdXN0IGEgVVJMLCB3aGljaCBjYW5ub3QgbmFtZSBhIHN0b3JlLiBXaGljaGV2ZXIgc3RvcmUncyBmb2xkZXIgaGFzIHRoZSBuZXdlc3QgY29weSBhbnN3ZXJzLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWRCdWNrZXRJbnRlcm5hbChhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZywgY29uZmlnOiB7IHBhdGg6IHN0cmluZzsgcmFuZ2U/OiB7IHN0YXJ0OiBudW1iZXI7IGVuZDogbnVtYmVyIH07IGluY2x1ZGVUb21ic3RvbmVzPzogYm9vbGVhbiB9KTogUHJvbWlzZTx7IGRhdGE6IEJ1ZmZlcjsgd3JpdGVUaW1lOiBudW1iZXI7IHNpemU6IG51bWJlciB9IHwgdW5kZWZpbmVkPiB7XG4gICAgbGV0IGJ1Y2tldCA9IGF3YWl0IHJlcXVpcmVCdWNrZXQoYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgbGV0IHJlc3VsdHMgPSBhd2FpdCBQcm9taXNlLmFsbChidWNrZXQuc3RvcmVzLm1hcChzID0+IHMuc3RvcmUuZ2V0Mih7IHBhdGg6IGNvbmZpZy5wYXRoLCByYW5nZTogY29uZmlnLnJhbmdlLCBpbmNsdWRlVG9tYnN0b25lczogY29uZmlnLmluY2x1ZGVUb21ic3RvbmVzLCBpbnRlcm5hbDogdHJ1ZSB9KSkpO1xuICAgIGxldCBiZXN0OiB7IGRhdGE6IEJ1ZmZlcjsgd3JpdGVUaW1lOiBudW1iZXI7IHNpemU6IG51bWJlciB9IHwgdW5kZWZpbmVkO1xuICAgIGZvciAobGV0IHJlc3VsdCBvZiByZXN1bHRzKSB7XG4gICAgICAgIGlmIChyZXN1bHQgJiYgKCFiZXN0IHx8IHJlc3VsdC53cml0ZVRpbWUgPiBiZXN0LndyaXRlVGltZSkpIHtcbiAgICAgICAgICAgIGJlc3QgPSByZXN1bHQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGJlc3Q7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRCdWNrZXRDb25maWcoYnVja2V0OiBCdWNrZXRTdGF0ZSk6IEFyY2hpdmVzQ29uZmlnIHtcbiAgICBsZXQgaW5kZXggPSB7IGZpbGVDb3VudDogMCwgYnl0ZUNvdW50OiAwIH07XG4gICAgbGV0IGluZGV4U291cmNlczogeyBkZWJ1Z05hbWU6IHN0cmluZzsgZmlsZUNvdW50OiBudW1iZXI7IGJ5dGVDb3VudDogbnVtYmVyIH1bXSA9IFtdO1xuICAgIGxldCBzeW5jaW5nOiBTeW5jQWN0aXZpdHlbXSA9IFtdO1xuICAgIGxldCByZWFkZXJEaXNrTGltaXQ6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgICBmb3IgKGxldCBzIG9mIGJ1Y2tldC5zdG9yZXMpIHtcbiAgICAgICAgbGV0IHByb2dyZXNzID0gcy5zdG9yZS5nZXRTeW5jUHJvZ3Jlc3MoKTtcbiAgICAgICAgaW5kZXguZmlsZUNvdW50ICs9IHByb2dyZXNzLmluZGV4LmZpbGVDb3VudDtcbiAgICAgICAgaW5kZXguYnl0ZUNvdW50ICs9IHByb2dyZXNzLmluZGV4LmJ5dGVDb3VudDtcbiAgICAgICAgaW5kZXhTb3VyY2VzLnB1c2goLi4ucHJvZ3Jlc3Muc291cmNlcyk7XG4gICAgICAgIHN5bmNpbmcucHVzaCguLi5wcm9ncmVzcy5zeW5jaW5nKTtcbiAgICAgICAgcmVhZGVyRGlza0xpbWl0ID0gcmVhZGVyRGlza0xpbWl0IHx8IHByb2dyZXNzLnJlYWRlckRpc2tMaW1pdDtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgLy8gRXZlcnkgc3RvcmUgaXMgaW5kZXgtYmFja2VkLCBzbyB0aGUgY2hhbmdlIGZlZWQgaXMgYWx3YXlzIG5hdGl2ZVxuICAgICAgICBzdXBwb3J0c0NoYW5nZXNBZnRlcjogdHJ1ZSxcbiAgICAgICAgcmVtb3RlQ29uZmlnOiBidWNrZXQucm91dGluZyxcbiAgICAgICAgaW5kZXgsXG4gICAgICAgIGluZGV4U291cmNlcyxcbiAgICAgICAgcmVhZGVyRGlza0xpbWl0LFxuICAgICAgICBzeW5jaW5nLFxuICAgIH07XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBidWNrZXRTeW5jU3RhdHVzKGJ1Y2tldDogQnVja2V0U3RhdGUpOiBQcm9taXNlPEFyY2hpdmVzU3luY1N0YXR1cz4ge1xuICAgIGxldCBzdGF0dXNlcyA9IGF3YWl0IFByb21pc2UuYWxsKGJ1Y2tldC5zdG9yZXMubWFwKHMgPT4gcy5zdG9yZS5nZXRTeW5jU3RhdHVzKCkpKTtcbiAgICByZXR1cm4ge1xuICAgICAgICBhbGxTY2Fuc0NvbXBsZXRlOiBzdGF0dXNlcy5ldmVyeSh4ID0+IHguYWxsU2NhbnNDb21wbGV0ZSksXG4gICAgICAgIGluZGV4U2l6ZTogc3RhdHVzZXMucmVkdWNlKChzdW0sIHgpID0+IHN1bSArIHguaW5kZXhTaXplLCAwKSxcbiAgICAgICAgc291cmNlczogc3RhdHVzZXMuZmxhdE1hcCh4ID0+IHguc291cmNlcyksXG4gICAgfTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGJ1Y2tldEluZGV4VG90YWxzKGJ1Y2tldDogQnVja2V0U3RhdGUpOiBQcm9taXNlPHsgZmlsZUNvdW50OiBudW1iZXI7IGJ5dGVDb3VudDogbnVtYmVyOyBzb3VyY2VzOiB7IGRlYnVnTmFtZTogc3RyaW5nOyBmaWxlQ291bnQ6IG51bWJlcjsgYnl0ZUNvdW50OiBudW1iZXIgfVtdIH0+IHtcbiAgICBsZXQgdG90YWxzID0gYXdhaXQgUHJvbWlzZS5hbGwoYnVja2V0LnN0b3Jlcy5tYXAocyA9PiBzLnN0b3JlLmNvbXB1dGVJbmRleFRvdGFscygpKSk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZmlsZUNvdW50OiB0b3RhbHMucmVkdWNlKChzdW0sIHgpID0+IHN1bSArIHguZmlsZUNvdW50LCAwKSxcbiAgICAgICAgYnl0ZUNvdW50OiB0b3RhbHMucmVkdWNlKChzdW0sIHgpID0+IHN1bSArIHguYnl0ZUNvdW50LCAwKSxcbiAgICAgICAgc291cmNlczogdG90YWxzLmZsYXRNYXAoeCA9PiB4LnNvdXJjZXMpLFxuICAgIH07XG59XG5cbmNvbnN0IGJ1Y2tldHMgPSBuZXcgTWFwPHN0cmluZywgUHJvbWlzZTxCdWNrZXRTdGF0ZSB8IHVuZGVmaW5lZD4+KCk7XG4vLyBUaGUgcmVzb2x2ZWQgb25lcywgZm9yIHRoZSBjb2RlIHRoYXQgd2Fsa3MgYnVja2V0cyByYXRoZXIgdGhhbiBhc2tpbmcgZm9yIG9uZSAoc2VlIGdldEJ1Y2tldFN0YXRlcylcbmNvbnN0IGxvYWRlZEJ1Y2tldHMgPSBuZXcgTWFwPHN0cmluZywgQnVja2V0U3RhdGU+KCk7XG5cbi8qKiBUaGUgYnVja2V0IHN0YXRlcyBjdXJyZW50bHkgaW4gbWVtb3J5IC0gd2hhdCB0aGUgc3dpdGNob3ZlciBtYWNoaW5lcnkgd2Fsa3MuIE9ubHkgd2hhdCBpcyBsb2FkZWQ6IGxvYWRpbmcgYSBidWNrZXQgc3RhcnRzIGl0cyBzeW5jaHJvbml6YXRpb24sIGFuZCBhIGJ1Y2tldCBub3RoaW5nIGhhcyB0b3VjaGVkIGhhcyBubyBpbi1mbGlnaHQgd3JpdGVzIHRvIGhhbmQgb3ZlciBhbnl3YXkuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0QnVja2V0U3RhdGVzKCk6IEJ1Y2tldFN0YXRlW10ge1xuICAgIHJldHVybiBbLi4ubG9hZGVkQnVja2V0cy52YWx1ZXMoKV07XG59XG5cbmNvbnN0IHJlc29sdmVkU291cmNlQXJjaGl2ZXMgPSBuZXcgTWFwPHN0cmluZywgSUFyY2hpdmVzPigpO1xuLyoqIEEgY2FjaGVkIElBcmNoaXZlcyBmb3IgYSBwZXJzaXN0ZWQgc291cmNlIGlkZW50aXR5OiBhIHJvdXRpbmcgVVJMIChob3N0ZWQvYmFja2JsYXplKSBvciBhIGRpc2sgZm9sZGVyIHBhdGggLSB0aGUgZm9ybSBCbG9iU3RvcmUncyBzb3VyY2VzIGxpc3Qgc3RvcmVzLiBDb25maWd1cmF0aW9uICh2YWxpZCB3aW5kb3dzLCByb3V0ZXMpIGRlY2lkZXMgV0hFTiBhIHNvdXJjZSBzaG91bGQgYmUgdXNlZDsgZm9yIHJlYWRpbmcgYnl0ZXMgdGhlIGluZGV4IHNheXMgYSBzb3VyY2UgaG9sZHMsIHRoZSBVUkwgYWxvbmUgaXMgZW5vdWdoIC0gZXZlbiBmb3Igc291cmNlcyBubyBsb25nZXIgaW4gYW55IGNvbmZpZy4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlU291cmNlQXJjaGl2ZXModXJsOiBzdHJpbmcpOiBJQXJjaGl2ZXMge1xuICAgIGxldCBleGlzdGluZyA9IHJlc29sdmVkU291cmNlQXJjaGl2ZXMuZ2V0KHVybCk7XG4gICAgaWYgKGV4aXN0aW5nKSByZXR1cm4gZXhpc3Rpbmc7XG4gICAgbGV0IHNvdXJjZUNvbmZpZzogU291cmNlQ29uZmlnIHwgdW5kZWZpbmVkO1xuICAgIGlmICh1cmwuc3RhcnRzV2l0aChcImh0dHBzOi8vXCIpKSB7XG4gICAgICAgIC8vIFRoZSBjb25maWcgaXMgZmFicmljYXRlZCBmcm9tIHRoZSBiYXJlIFVSTCBhbmQgY2FuIG5ldmVyIGV4YWN0LW1hdGNoIGEgc2VydmVyJ3MgZW50cmllcyAtIHdoaWNoIGlzIGZpbmUsIGJlY2F1c2UgaG9sZGVyIHJlYWRzIGFyZSBpbnRlcm5hbCByZWFkcywgYW5kIGludGVybmFsIHJlYWRzIG5ldmVyIHNlbGVjdCBhIHN0b3JlIChzZWUgcmVhZEJ1Y2tldEludGVybmFsKVxuICAgICAgICBzb3VyY2VDb25maWcgPSBub3JtYWxpemVTb3VyY2UodXJsKTtcbiAgICB9XG4gICAgbGV0IGFyY2hpdmVzID0gY3JlYXRlU3RvcmVTb3VyY2UoeyBzb3VyY2VDb25maWcsIGZvbGRlcjogdXJsIH0pO1xuICAgIHJlc29sdmVkU291cmNlQXJjaGl2ZXMuc2V0KHVybCwgYXJjaGl2ZXMpO1xuICAgIHJldHVybiBhcmNoaXZlcztcbn1cblxuLyoqIFdoYXQgYW4gaW5kZXggZW50cnkgcmVjb3JkcyBhcyB0aGUgaG9sZGVyIG9mIGl0cyBieXRlcyAoc2VlIEFyY2hpdmVzU291cmNlLnVybCksIHNvIGl0IG11c3QgbmFtZSB0aGUgZW5kcG9pbnQgRk9SRVZFUi4gQW4gaW50ZXJtZWRpYXRlIGlzIGEgc3dpdGNob3ZlcidzIHRlbXBvcmFyeSBhbHRlcm5hdGUgcG9ydCBvbnRvIGFub3RoZXIgc291cmNlLCBhbmQgdGhhdCBwb3J0IGlzIGdvbmUgZm9yIGdvb2Qgb25jZSBpdHMgd2luZG93IHBhc3NlcyAtIHNvIGl0IGlzIHJlY29yZGVkIGFzIHRoZSBzb3VyY2UgaXQgd2FzIHNwbGl0IG91dCBvZiwgd2hpY2ggaG9sZHMgdGhlIHNhbWUgYnVja2V0IGFuZCBvdXRsaXZlcyBpdC4gKi9cbmZ1bmN0aW9uIHNvdXJjZVBlcnNpc3RlbnRVcmwoc291cmNlQ29uZmlnOiBTb3VyY2VDb25maWcgfCB1bmRlZmluZWQsIGZvbGRlcjogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBpZiAoIXNvdXJjZUNvbmZpZykgcmV0dXJuIGZvbGRlcjtcbiAgICByZXR1cm4gc291cmNlQ29uZmlnLmludGVybWVkaWF0ZSB8fCBzb3VyY2VDb25maWcudXJsO1xufVxuXG4vKiogVGhlIGZhc3Qtd3JpdGUgcG9saWN5IHRoaXMgc3RvcmUgd3JpdGVzIHVuZGVyOiBpdHMgb3duIGNvbmZpZ3VyYXRpb24gZGVjaWRlcyBpdCAoZmFzdC93cml0ZURlbGF5IGFyZSBPVVIgc2V0dGluZ3MsIG5vdCB0aGUgcGVlcidzKSwgYW5kIGVhY2ggc291cmNlIHRoZW4gaG9sZHMgd3JpdGVzIGZvciBhcyBsb25nIGFzIHNvdXJjZVdyaXRlRGVsYXkgc2F5cy4gKi9cbi8qKlxuICogRXZlcnkgc3RvcmUgdGhpcyBwcm9jZXNzIHJ1bnMsIGJ5IGZvbGRlciAtIHdoaWNoIElTIHRoZSBzdG9yZSdzIGlkZW50aXR5OiBhY2NvdW50LCBuYW1lLCBidWNrZXQuXG4gKiBBIHN0b3JlIGlzIG1hZGUgb25jZSwgY29uZmlndXJlcyBpdHNlbGYgZnJvbSB0aGUgcm91dGluZyBjb25maWcgaXQgaG9sZHMsIGFuZCBzdGF5czsgbm90aGluZyBoZXJlXG4gKiBkZWNpZGVzIHdoYXQgaXQgaXMsIG9ubHkgdGhhdCBpdCBleGlzdHMuXG4gKi9cbmNvbnN0IHN0b3JlcyA9IG5ldyBNYXA8c3RyaW5nLCBCbG9iU3RvcmU+KCk7XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTdG9yZShhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZywgbmFtZTogc3RyaW5nKTogQmxvYlN0b3JlIHtcbiAgICBsZXQgZm9sZGVyID0gZ2V0QnVja2V0Rm9sZGVyKG5hbWUsIGFjY291bnQsIGJ1Y2tldE5hbWUpO1xuICAgIGxldCBleGlzdGluZyA9IHN0b3Jlcy5nZXQoZm9sZGVyKTtcbiAgICBpZiAoZXhpc3RpbmcpIHJldHVybiBleGlzdGluZztcbiAgICBsZXQgc3RvcmUgPSBuZXcgQmxvYlN0b3JlKGZvbGRlciwgbmFtZSwge1xuICAgICAgICAvLyBXaGljaCBlbnRyaWVzIGluIElUUyByb3V0aW5nIGNvbmZpZyBhcmUgdGhpcyBzZXJ2ZXIncyBjb3B5IG9mIGl0XG4gICAgICAgIGlzU2VsZjogc291cmNlID0+IGlzU2VsZlNvdXJjZShzb3VyY2UsIGFjY291bnQsIGJ1Y2tldE5hbWUpLFxuICAgICAgICBjcmVhdGVTb3VyY2U6IGNvbmZpZyA9PiBjcmVhdGVTdG9yZVNvdXJjZSh7IHNvdXJjZUNvbmZpZzogY29uZmlnLnNvdXJjZUNvbmZpZywgZm9sZGVyLCB3cml0ZURlbGF5OiBjb25maWcud3JpdGVEZWxheSB9KSxcbiAgICAgICAgYXBwbHlTb3VyY2U6IChzb3VyY2UsIHNvdXJjZUNvbmZpZywgd3JpdGVEZWxheSkgPT4gYXBwbHlTb3VyY2VDb25maWcoc291cmNlLCBzb3VyY2VDb25maWcsIHdyaXRlRGVsYXkpLFxuICAgICAgICBvbldyaXRlQ291bnRlZDogKGtpbmQsIGJ5dGVzKSA9PiBjb3VudEJ1Y2tldFdyaXRlKGAke2FjY291bnR9LyR7YnVja2V0TmFtZX1gLCBraW5kLCBieXRlcyksXG4gICAgICAgIHJlc29sdmVTb3VyY2VVcmw6IHJlc29sdmVTb3VyY2VBcmNoaXZlcyxcbiAgICB9KTtcbiAgICBzdG9yZXMuc2V0KGZvbGRlciwgc3RvcmUpO1xuICAgIC8vIExhenkgaW5pdCB3b3VsZCBsZWF2ZSBhIHN0b3JlIG5vdGhpbmcgaGFzIHRvdWNoZWQgc2l0dGluZyBpbmVydCAtIG5vIGluZGV4IGxvYWRlZCwgbm8gY29uZmlnIGFwcGxpZWQsIG5vdGhpbmcgc3luY2hyb25pemluZyAtIHdoaWxlIGl0cyBmb2xkZXIgaXMgZnVsbCBvZiBmaWxlc1xuICAgIHZvaWQgc3RvcmUuaW5pdCgpLmNhdGNoKChlOiBFcnJvcikgPT4gY29uc29sZS5lcnJvcihgSW5pdGlhbGl6aW5nIHN0b3JlICR7SlNPTi5zdHJpbmdpZnkobmFtZSl9IG9mIGJ1Y2tldCAke2FjY291bnR9LyR7YnVja2V0TmFtZX0gZmFpbGVkOiAke2Uuc3RhY2sgPz8gZX1gKSk7XG4gICAgcmV0dXJuIHN0b3JlO1xufVxuXG4vKiogVGhlIGJ1Y2tldCBhcyB0aGlzIHNlcnZlciBoYXMgaXQ6IHRoZSBzdG9yZXMgd2hvc2UgZm9sZGVycyBleGlzdCwgcGx1cyB3aGF0ZXZlciB0aGUgbmV3ZXN0IG9mIHRoZWlyIGNvbmZpZ3Mgc2F5cyBhYm91dCB1cy4gTmFtZXMgY29tZSBmcm9tIHRoZSBESVNLLCBub3QgZnJvbSB0aGUgY29uZmlnIC0gYSBzdG9yZSB3ZSBob2xkIGtlZXBzIGJlaW5nIHNlcnZlZCB3aGV0aGVyIG9yIG5vdCB0aGUgY3VycmVudCBjb25maWcgc3RpbGwgbWVudGlvbnMgaXQuICovXG5mdW5jdGlvbiBidWlsZEJ1Y2tldChhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZywgbmFtZXM6IHN0cmluZ1tdLCByb3V0aW5nOiBSZW1vdGVDb25maWcgfCB1bmRlZmluZWQpOiBCdWNrZXRTdGF0ZSB7XG4gICAgbGV0IHBsYW4gPSByb3V0aW5nICYmIHBsYW5TZWxmU3RvcmVzKGFjY291bnQsIGJ1Y2tldE5hbWUsIHJvdXRpbmcpIHx8IHVuZGVmaW5lZDtcbiAgICBsZXQgZW50cmllc0J5TmFtZSA9IG5ldyBNYXA8c3RyaW5nLCBIb3N0ZWRDb25maWdbXT4oKTtcbiAgICBmb3IgKGxldCBzZWxmU3RvcmUgb2YgcGxhbj8uc3RvcmVzIHx8IFtdKSB7XG4gICAgICAgIGVudHJpZXNCeU5hbWUuc2V0KHNlbGZTdG9yZS5uYW1lLCBzZWxmU3RvcmUuZW50cmllcyk7XG4gICAgfVxuICAgIC8vIEVhY2ggc3RvcmUgcmVhZHMgaXRzIG93biBjb3B5IG9mIHRoZSBjb25maWcgYW5kIGRlY2lkZXMgd2hhdCBpdCBpcyAtIHNlZSBCbG9iU3RvcmUuYXBwbHlSb3V0aW5nQ29uZmlnLiBOb3RoaW5nIGhlcmUgY29uZmlndXJlcyBhbnl0aGluZy5cbiAgICBsZXQgc3RvcmVzOiBMb2FkZWRTdG9yZVtdID0gbmFtZXMubWFwKG5hbWUgPT4gKHtcbiAgICAgICAgbmFtZSxcbiAgICAgICAgZW50cmllczogZW50cmllc0J5TmFtZS5nZXQobmFtZSkgfHwgW10sXG4gICAgICAgIGZvbGRlcjogZ2V0QnVja2V0Rm9sZGVyKG5hbWUsIGFjY291bnQsIGJ1Y2tldE5hbWUpLFxuICAgICAgICBzdG9yZTogZ2V0U3RvcmUoYWNjb3VudCwgYnVja2V0TmFtZSwgbmFtZSksXG4gICAgfSkpO1xuICAgIGxldCBsb2FkZWQ6IEJ1Y2tldFN0YXRlID0geyBhY2NvdW50LCBidWNrZXROYW1lLCByb3V0aW5nLCBzZWxmRW50cmllczogcGxhbj8uc2VsZkVudHJpZXMgfHwgW10sIHNlbGY6IHBsYW4/LnNlbGYsIHN0b3JlcyB9O1xuICAgIGxvYWRlZEJ1Y2tldHMuc2V0KGAke2FjY291bnR9LyR7YnVja2V0TmFtZX1gLCBsb2FkZWQpO1xuICAgIHNjaGVkdWxlQm91bmRhcnlXb3JrKGxvYWRlZCk7XG4gICAgcmV0dXJuIGxvYWRlZDtcbn1cblxuLy8gQSBidWNrZXQgZXhpc3RzIGhlcmUgd2hlbiBpdCBoYXMgYXQgbGVhc3Qgb25lIHN0b3JlIGZvbGRlciAtIHRoZSBkaXNrIElTIHRoZSByZWNvcmQuIEl0cyBjb25maWcgaXMgdGhlIG5ld2VzdCBjb3B5IGFtb25nIHRob3NlIHN0b3Jlczsgd2l0aCBub25lIGF0IGFsbCBpdCBoYXMgbm8gY29uZmlnIHlldCwgd2hpY2ggaXMgYSBwZXJmZWN0bHkgZ29vZCBzdGF0ZSBmb3IgYSBzdG9yZSBub2JvZHkgaGFzIGNvbmZpZ3VyZWQuXG5hc3luYyBmdW5jdGlvbiBsb2FkQnVja2V0KGFjY291bnQ6IHN0cmluZywgYnVja2V0TmFtZTogc3RyaW5nKTogUHJvbWlzZTxCdWNrZXRTdGF0ZSB8IHVuZGVmaW5lZD4ge1xuICAgIGxldCBmb2xkZXJzID0gYXdhaXQgbGlzdEJ1Y2tldFN0b3JlRm9sZGVycyhhY2NvdW50LCBidWNrZXROYW1lKTtcbiAgICBpZiAoIWZvbGRlcnMubGVuZ3RoKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGxldCByb3V0aW5nID0gYXdhaXQgcmVhZFJvdXRpbmdGcm9tRGlzayhhY2NvdW50LCBidWNrZXROYW1lKTtcbiAgICByZXR1cm4gYnVpbGRCdWNrZXQoYWNjb3VudCwgYnVja2V0TmFtZSwgZm9sZGVycy5tYXAoeCA9PiB4Lm5hbWUpLCByb3V0aW5nKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldExvYWRlZEJ1Y2tldChhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZyk6IFByb21pc2U8QnVja2V0U3RhdGUgfCB1bmRlZmluZWQ+IHtcbiAgICBsZXQga2V5ID0gYCR7YWNjb3VudH0vJHtidWNrZXROYW1lfWA7XG4gICAgcmV0dXJuIGJ1Y2tldHMuZ2V0KGtleSkgfHwgcmVsb2FkQnVja2V0KGFjY291bnQsIGJ1Y2tldE5hbWUpO1xufVxuXG4vKiogUmUtcmVhZHMgdGhlIGJ1Y2tldCBvZmYgdGhlIGRpc2ssIHJlcGxhY2luZyB0aGUgY2FjaGVkIHNuYXBzaG90OiB3aGF0IGEgcm91dGluZy1jb25maWcgd3JpdGUgY2FsbHMsIGJlY2F1c2UgdGhhdCB3cml0ZSBjYW4gQ1JFQVRFIGEgc3RvcmUgKGEgbmV3IG5hbWUgZ2V0cyBhIG5ldyBmb2xkZXIpIGFuZCB0aGUgc25hcHNob3Qgd291bGQga2VlcCBhbnN3ZXJpbmcgd2l0aCB0aGUgc3RvcmVzIGl0IHNhdyBhdCBsb2FkIHRpbWUuIEV4aXN0aW5nIHN0b3JlcyBhcmUgcmV1c2VkIChnZXRTdG9yZSBjYWNoZXMgYnkgZm9sZGVyKSwgc28gdGhpcyBvbmx5IHBpY2tzIHVwIGZvbGRlciBjaGFuZ2VzIC0gaXQgbmV2ZXIgcmVzdGFydHMgYSBzdG9yZS4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWxvYWRCdWNrZXQoYWNjb3VudDogc3RyaW5nLCBidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPEJ1Y2tldFN0YXRlIHwgdW5kZWZpbmVkPiB7XG4gICAgbGV0IGtleSA9IGAke2FjY291bnR9LyR7YnVja2V0TmFtZX1gO1xuICAgIGxldCBsb2FkZWQgPSBsb2FkQnVja2V0KGFjY291bnQsIGJ1Y2tldE5hbWUpO1xuICAgIGJ1Y2tldHMuc2V0KGtleSwgbG9hZGVkKTtcbiAgICB2b2lkIGxvYWRlZC50aGVuKGJ1Y2tldCA9PiB7XG4gICAgICAgIGlmICghYnVja2V0ICYmIGJ1Y2tldHMuZ2V0KGtleSkgPT09IGxvYWRlZCkge1xuICAgICAgICAgICAgYnVja2V0cy5kZWxldGUoa2V5KTtcbiAgICAgICAgfVxuICAgIH0sICgpID0+IHtcbiAgICAgICAgaWYgKGJ1Y2tldHMuZ2V0KGtleSkgPT09IGxvYWRlZCkge1xuICAgICAgICAgICAgYnVja2V0cy5kZWxldGUoa2V5KTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiBhd2FpdCBsb2FkZWQ7XG59XG5cbi8qKlxuICogV3JpdGluZyB0aGUgcm91dGluZyBjb25maWcgaXMgYSB3cml0ZSBsaWtlIGFueSBvdGhlcjogaXQgZ29lcyBpbnRvIGEgc3RvcmUsIGFuZCB0aGUgc3RvcmUgYXBwbGllc1xuICogaXQgdG8gaXRzZWxmIGFuZCBsZXRzIGl0cyBwZWVycyBwdWxsIGl0LiBUaGUgb25seSB0aGluZyB0aGF0IGhhcHBlbnMgaGVyZSBpcyBwaWNraW5nIFdISUNIIHN0b3JlLFxuICogYmVjYXVzZSB0aGUgd3JpdGVyIG5hbWVzIGEgc291cmNlIGFuZCBhIHNvdXJjZSBuYW1lcyBhIHN0b3JlLlxuICpcbiAqIEluLWZsaWdodCBzd2l0Y2hvdmVyIHdpbmRvd3MgYXJlIHJlLWluamVjdGVkIGZpcnN0IChzZWUgaW50ZXJtZWRpYXRlTWFuYWdlbWVudCk6IGFuIG9wZXJhdG9yJ3NcbiAqIGNvbmZpZyBrbm93cyBub3RoaW5nIGFib3V0IGEgc3dpdGNob3ZlciB0aGF0IGlzIGhhcHBlbmluZyByaWdodCBub3csIGFuZCB3cml0aW5nIGl0IGFzLWlzIHdvdWxkXG4gKiBjYW5jZWwgaXQgbWlkLWZsaWdodC5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHdyaXRlUm91dGluZ0NvbmZpZyhhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZywgbmFtZTogc3RyaW5nLCBkYXRhOiBCdWZmZXIsIGNvbmZpZz86IHsgbGFzdE1vZGlmaWVkPzogbnVtYmVyIH0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhc3NlcnRXcml0ZXNBbGxvd2VkKCk7XG4gICAgbGV0IHN0b3JlID0gZ2V0U3RvcmUoYWNjb3VudCwgYnVja2V0TmFtZSwgbmFtZSk7XG4gICAgbGV0IGluY29taW5nID0gcGFyc2VSb3V0aW5nRGF0YShkYXRhKTtcbiAgICBsZXQgY3VycmVudCA9IChhd2FpdCBnZXRMb2FkZWRCdWNrZXQoYWNjb3VudCwgYnVja2V0TmFtZSkpPy5yb3V0aW5nO1xuICAgIGxldCBzdG9yZWQgPSByZWluamVjdEludGVybWVkaWF0ZXMoY3VycmVudCwgaW5jb21pbmcpO1xuICAgIGF3YWl0IHN0b3JlLnNldCh7IHBhdGg6IFJPVVRJTkdfRklMRSwgZGF0YTogQnVmZmVyLmZyb20oc2VyaWFsaXplUmVtb3RlQ29uZmlnKHN0b3JlZCkpLCBsYXN0TW9kaWZpZWQ6IGNvbmZpZz8ubGFzdE1vZGlmaWVkIH0pO1xuICAgIC8vIFRoZSB3cml0ZSBtYXkgaGF2ZSBDUkVBVEVEIHRoZSBzdG9yZSAoYSBuZXcgbmFtZSBnZXRzIGEgbmV3IGZvbGRlciksIGFuZCB0aGUgbG9hZGVkIGJ1Y2tldCBpcyBhIHNuYXBzaG90IG9mIHRoZSBkaXNrIC0gc28gaXQgaXMgcmUtcmVhZCwgb3IgZXZlcnkgZGF0YSB3cml0ZSBuYW1pbmcgdGhlIG5ldyBzdG9yZSBpcyByZWplY3RlZCB1bnRpbCBhIHJlc3RhcnRcbiAgICBhd2FpdCByZWxvYWRCdWNrZXQoYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgYnJvYWRjYXN0Um91dGluZ0NoYW5nZWQoKTtcbn1cblxuLyoqIFdoaWNoIGJ1Y2tldHMgdGhpcyBwcm9jZXNzIGN1cnJlbnRseSBoYXMgbG9hZGVkIC0gd2hhdCBhIGRlcGxveSBzdWNjZXNzb3IgYXNrcyBpdHMgcHJlZGVjZXNzb3IgZm9yLCBzbyBpdCBhY3RpdmF0ZXMgZXhhY3RseSB0aGUgYnVja2V0cyB0aGF0IGFyZSBhY3R1YWxseSBpbiB1c2UuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0QWN0aXZlQnVja2V0S2V5cygpOiB7IGFjY291bnQ6IHN0cmluZzsgYnVja2V0TmFtZTogc3RyaW5nIH1bXSB7XG4gICAgcmV0dXJuIFsuLi5idWNrZXRzLmtleXMoKV0ubWFwKGtleSA9PiB7XG4gICAgICAgIGxldCBzbGFzaCA9IGtleS5pbmRleE9mKFwiL1wiKTtcbiAgICAgICAgcmV0dXJuIHsgYWNjb3VudDoga2V5LnNsaWNlKDAsIHNsYXNoKSwgYnVja2V0TmFtZToga2V5LnNsaWNlKHNsYXNoICsgMSkgfTtcbiAgICB9KTtcbn1cblxuZXhwb3J0IHR5cGUgU2VydmVyQnVja2V0SW5mbyA9IHtcbiAgICBidWNrZXROYW1lOiBzdHJpbmc7XG4gICAgYWN0aXZlOiBib29sZWFuO1xuICAgIC8qKiBXaGVyZSB0aGUgYnVja2V0J3MgZGF0YSBsaXZlcyBvbiB0aGlzIHNlcnZlciAqL1xuICAgIGZvbGRlcjogc3RyaW5nO1xuICAgIC8qKiBUaGUgZHJpdmUgdGhhdCBmb2xkZXIgaXMgb24uIEJ1Y2tldHMgc2hhcmluZyBhIGRyaXZlIHJlcG9ydCB0aGUgc2FtZSBudW1iZXJzLiAqL1xuICAgIGRpc2s/OiBCdWNrZXREaXNrSW5mbztcbiAgICBkaXNrRXJyb3I/OiBzdHJpbmc7XG4gICAgd3JpdGVTdGF0cz86IEJ1Y2tldFdyaXRlU3RhdHM7XG4gICAgY29uZmlnPzogQXJjaGl2ZXNDb25maWc7XG4gICAgZXJyb3I/OiBzdHJpbmc7XG59O1xuXG5leHBvcnQgdHlwZSBBY3RpdmVCdWNrZXRJbmZvID0ge1xuICAgIGZvbGRlcjogc3RyaW5nO1xuICAgIC8qKiBUaGUgcm91dGluZyBjb25maWcgdGhlIGJ1Y2tldCBpcyBSVU5OSU5HIG9uLCBzdHJhaWdodCBmcm9tIG1lbW9yeSAtIGluY2x1ZGluZyBzd2l0Y2hvdmVyIHdpbmRvd3Mgd3JpdHRlbiBzaW5jZSBpdCBsb2FkZWQuIEFic2VudCB3aGVuIG5vbmUgb2YgaXRzIHN0b3JlcyBoYXMgb25lIHlldC4gKi9cbiAgICByb3V0aW5nPzogUmVtb3RlQ29uZmlnO1xuICAgIC8qKiBPdXIgb3duIGVudHJpZXMgaW4gdGhhdCBjb25maWcsIGFuZCB0aGVpciBzdW1tYXJpemVkIGN1cnJlbnQgcm9sZSAocm91dGVzIHVuaW9uICsgZmxhZ3MpICovXG4gICAgc2VsZkVudHJpZXM6IEhvc3RlZENvbmZpZ1tdO1xuICAgIHNlbGY/OiBTZWxmU3VtbWFyeTtcbiAgICBjb25maWc6IEFyY2hpdmVzQ29uZmlnO1xufTtcblxuZnVuY3Rpb24gdG9BY3RpdmVCdWNrZXRJbmZvKGxvYWRlZDogQnVja2V0U3RhdGUpOiBBY3RpdmVCdWNrZXRJbmZvIHtcbiAgICByZXR1cm4ge1xuICAgICAgICAvLyBPbmUgb2YgaXRzIHN0b3JlcycgZm9sZGVycyAtIGEgYnVja2V0IG5vIGxvbmdlciBoYXMgYSBmb2xkZXIgb2YgaXRzIG93biwgaXQgaGFzIG9uZSBwZXIgc3RvcmVcbiAgICAgICAgZm9sZGVyOiBsb2FkZWQuc3RvcmVzWzBdPy5mb2xkZXIgfHwgXCJcIixcbiAgICAgICAgcm91dGluZzogbG9hZGVkLnJvdXRpbmcsXG4gICAgICAgIHNlbGZFbnRyaWVzOiBsb2FkZWQuc2VsZkVudHJpZXMsXG4gICAgICAgIHNlbGY6IGxvYWRlZC5zZWxmLFxuICAgICAgICBjb25maWc6IGdldEJ1Y2tldENvbmZpZyhsb2FkZWQpLFxuICAgIH07XG59XG5cbi8qKiBUaGUgbGl2ZSBpbi1tZW1vcnkgc3RhdGUgb2YgT05FIGJ1Y2tldCwgYW5zd2VyZWQgd2l0aG91dCB0b3VjaGluZyB0aGUgZGlzayAobm8gcm91dGluZyBmaWxlIHJlYWQsIG5vIHN0YXRmcywgbm8gc3RvcmVkIHdyaXRlIHN0YXRzKS4gUmV0dXJucyBhbiBlcnJvciBzdHJpbmcgd2hlbiB0aGUgYnVja2V0IGlzIG5vdCBsb2FkZWQgaGVyZSwgd2hpY2ggaXMgdGhlIG5vcm1hbCBzdGF0ZSBmb3IgYSBidWNrZXQgbm90aGluZyBoYXMgYWNjZXNzZWQgc2luY2Ugc3RhcnR1cC4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRBY3RpdmVCdWNrZXQoYWNjb3VudDogc3RyaW5nLCBidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPEFjdGl2ZUJ1Y2tldEluZm8gfCBzdHJpbmc+IHtcbiAgICBsZXQga2V5ID0gYCR7YWNjb3VudH0vJHtidWNrZXROYW1lfWA7XG4gICAgbGV0IGxvYWRlZFByb21pc2UgPSBidWNrZXRzLmdldChrZXkpO1xuICAgIGlmICghbG9hZGVkUHJvbWlzZSkge1xuICAgICAgICByZXR1cm4gYEJ1Y2tldCAke2tleX0gaXMgbm90IGxvYWRlZCBvbiB0aGlzIHNlcnZlciwgc28gaXQgaGFzIG5vIGxpdmUgc3RhdGUgKGl0IGxvYWRzIG9uIGZpcnN0IGFjY2VzcylgO1xuICAgIH1cbiAgICBsZXQgbG9hZGVkOiBCdWNrZXRTdGF0ZSB8IHVuZGVmaW5lZDtcbiAgICB0cnkge1xuICAgICAgICBsb2FkZWQgPSBhd2FpdCBsb2FkZWRQcm9taXNlO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmV0dXJuIGBCdWNrZXQgJHtrZXl9IGZhaWxlZCB0byBsb2FkIG9uIHRoaXMgc2VydmVyOiAke1N0cmluZygoZSBhcyBFcnJvcikuc3RhY2sgPz8gZSkuc2xpY2UoMCwgNTAwKX1gO1xuICAgIH1cbiAgICBpZiAoIWxvYWRlZCkge1xuICAgICAgICByZXR1cm4gYEJ1Y2tldCAke2tleX0gZG9lcyBub3QgZXhpc3Qgb24gdGhpcyBzZXJ2ZXJgO1xuICAgIH1cbiAgICByZXR1cm4gdG9BY3RpdmVCdWNrZXRJbmZvKGxvYWRlZCk7XG59XG5cbi8qKiBMb2FkcyBhIGJ1Y2tldCB0aGF0IGV4aXN0cyBvbiB0aGlzIHNlcnZlcidzIGRpc2sgaW50byBtZW1vcnksIHdoaWNoIHN0YXJ0cyBpdHMgc3luY2hyb25pemF0aW9uIGFuZCB3aW5kb3cgdGltZXJzLCBhbmQgcmV0dXJucyBpdHMgbGl2ZSBzdGF0ZS4gTm90aGluZyBpcyB3cml0dGVuIGFuZCBubyBvdGhlciBzZXJ2ZXIgaXMgY29udGFjdGVkIC0gdW5saWtlIGJ1aWxkaW5nIGFuIEFyY2hpdmVzQ2hhaW4gZm9yIGl0LCB3aGljaCB3b3VsZCBwcm9iZSBldmVyeSBzb3VyY2UgYW5kIGNvdWxkIHdyaXRlIHRoZSByb3V0aW5nIGNvbmZpZy4gQWxyZWFkeS1sb2FkZWQgYnVja2V0cyBqdXN0IHJldHVybiB0aGVpciBzdGF0ZS4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhY3RpdmF0ZUJ1Y2tldChhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZyk6IFByb21pc2U8QWN0aXZlQnVja2V0SW5mbyB8IHN0cmluZz4ge1xuICAgIGxldCBrZXkgPSBgJHthY2NvdW50fS8ke2J1Y2tldE5hbWV9YDtcbiAgICBsZXQgd2FzTG9hZGVkID0gYnVja2V0cy5oYXMoa2V5KTtcbiAgICBsZXQgbG9hZGVkOiBCdWNrZXRTdGF0ZSB8IHVuZGVmaW5lZDtcbiAgICB0cnkge1xuICAgICAgICBsb2FkZWQgPSBhd2FpdCBnZXRMb2FkZWRCdWNrZXQoYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZXR1cm4gYEJ1Y2tldCAke2tleX0gZmFpbGVkIHRvIGxvYWQgb24gdGhpcyBzZXJ2ZXI6ICR7U3RyaW5nKChlIGFzIEVycm9yKS5zdGFjayA/PyBlKS5zbGljZSgwLCA1MDApfWA7XG4gICAgfVxuICAgIGlmICghbG9hZGVkKSB7XG4gICAgICAgIHJldHVybiBgQnVja2V0ICR7a2V5fSBkb2VzIG5vdCBleGlzdCBvbiB0aGlzIHNlcnZlciAoaXQgaGFzIG5vIHN0b3JlIGZvbGRlcnMgdW5kZXIgJHtnZXRCdWNrZXRGb2xkZXIoXCI8bmFtZT5cIiwgYWNjb3VudCwgYnVja2V0TmFtZSl9KWA7XG4gICAgfVxuICAgIC8vIFdhaXQgZm9yIHRoZSBpbmRleGVzIHRvIGxvYWQsIHNvIHRoZSB0b3RhbHMgd2UgcmV0dXJuIGFyZSB0aGUgcmVhbCBvbmVzIHJhdGhlciB0aGFuIHplcm9lcyBmcm9tIHN0b3JlcyB0aGF0IGhhdmUgbm90IHJlYWQgdGhlaXIgaW5kZXggeWV0LiBUaGUgc291cmNlIHNjYW5zIGtlZXAgcnVubmluZyBpbiB0aGUgYmFja2dyb3VuZC5cbiAgICBmb3IgKGxldCBzIG9mIGxvYWRlZC5zdG9yZXMpIHtcbiAgICAgICAgYXdhaXQgcy5zdG9yZS5pbml0KCk7XG4gICAgfVxuICAgIGlmICghd2FzTG9hZGVkKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKGBBY3RpdmF0ZWQgYnVja2V0ICR7a2V5fSBvbiByZXF1ZXN0OiBpdCBpcyBub3cgbG9hZGVkIGFuZCBzeW5jaHJvbml6aW5nYCk7XG4gICAgfVxuICAgIHJldHVybiB0b0FjdGl2ZUJ1Y2tldEluZm8obG9hZGVkKTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGxpc3RBY2NvdW50QnVja2V0cyhhY2NvdW50OiBzdHJpbmcpOiBQcm9taXNlPFNlcnZlckJ1Y2tldEluZm9bXT4ge1xuICAgIGxldCBzdGFydCA9IERhdGUubm93KCk7XG4gICAgbGV0IHRpbWluZ3MgPSBuZXcgTWFwPHN0cmluZywgbnVtYmVyPigpO1xuICAgIGFzeW5jIGZ1bmN0aW9uIHRpbWVkPFQ+KG5hbWU6IHN0cmluZywgcnVuOiAoKSA9PiBQcm9taXNlPFQ+KTogUHJvbWlzZTxUPiB7XG4gICAgICAgIGxldCBiZWdhbiA9IERhdGUubm93KCk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgcnVuKCk7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgICB0aW1pbmdzLnNldChuYW1lLCAodGltaW5ncy5nZXQobmFtZSkgfHwgMCkgKyAoRGF0ZS5ub3coKSAtIGJlZ2FuKSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgLy8gVGhlIGRpc2sgaXMgdGhlIHJlY29yZDogYSBidWNrZXQgZXhpc3RzIGhlcmUgd2hlbiBpdCBoYXMgYXQgbGVhc3Qgb25lIHN0b3JlIGZvbGRlciwgYW5kIHNldmVyYWwgbmFtZXMgZm9yIG9uZSBidWNrZXQgYXJlIHN0aWxsIG9uZSBidWNrZXRcbiAgICBsZXQgZm9sZGVycyA9IGF3YWl0IHRpbWVkKFwicmVhZGRpclwiLCAoKSA9PiBsaXN0QWNjb3VudFN0b3JlRm9sZGVycyhhY2NvdW50KSk7XG4gICAgbGV0IGJ5QnVja2V0ID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZz4oKTtcbiAgICBmb3IgKGxldCBzdG9yZSBvZiBmb2xkZXJzKSB7XG4gICAgICAgIGlmIChieUJ1Y2tldC5oYXMoc3RvcmUuYnVja2V0TmFtZSkpIGNvbnRpbnVlO1xuICAgICAgICBieUJ1Y2tldC5zZXQoc3RvcmUuYnVja2V0TmFtZSwgc3RvcmUuZm9sZGVyKTtcbiAgICB9XG4gICAgbGV0IG5hbWVzID0gWy4uLmJ5QnVja2V0LmtleXMoKV07XG4gICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGF3YWl0IFByb21pc2UuYWxsKG5hbWVzLm1hcChhc3luYyBidWNrZXROYW1lID0+IHtcbiAgICAgICAgICAgIGxldCBrZXkgPSBgJHthY2NvdW50fS8ke2J1Y2tldE5hbWV9YDtcbiAgICAgICAgICAgIGxldCBmb2xkZXIgPSBieUJ1Y2tldC5nZXQoYnVja2V0TmFtZSkgfHwgXCJcIjtcbiAgICAgICAgICAgIGxldCBiYXNlOiBTZXJ2ZXJCdWNrZXRJbmZvID0geyBidWNrZXROYW1lLCBhY3RpdmU6IGZhbHNlLCBmb2xkZXIgfTtcbiAgICAgICAgICAgIGJhc2UuZGlzayA9IGF3YWl0IHRpbWVkKFwic3RhdGZzXCIsICgpID0+IGdldERpc2tJbmZvKGZvbGRlcikpLmNhdGNoKChlOiBFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIGJhc2UuZGlza0Vycm9yID0gU3RyaW5nKGUuc3RhY2sgPz8gZSkuc2xpY2UoMCwgNTAwKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBiYXNlLndyaXRlU3RhdHMgPSBnZXRCdWNrZXRXcml0ZVN0YXRzKGtleSk7XG4gICAgICAgICAgICBjb25zdCBsb2FkZWRQcm9taXNlID0gYnVja2V0cy5nZXQoa2V5KTtcbiAgICAgICAgICAgIGlmIChsb2FkZWRQcm9taXNlKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgbGV0IGxvYWRlZCA9IGF3YWl0IHRpbWVkKFwiYXdhaXRMb2FkZWRcIiwgKCkgPT4gbG9hZGVkUHJvbWlzZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChsb2FkZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7IC4uLmJhc2UsIGFjdGl2ZTogdHJ1ZSwgY29uZmlnOiBnZXRCdWNrZXRDb25maWcobG9hZGVkKSB9O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4geyAuLi5iYXNlLCBhY3RpdmU6IHRydWUsIGVycm9yOiBTdHJpbmcoKGUgYXMgRXJyb3IpLnN0YWNrID8/IGUpLnNsaWNlKDAsIDUwMCkgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHBhcnNlZCA9IGF3YWl0IHRpbWVkKFwicmVhZFJvdXRpbmdGaWxlXCIsICgpID0+IHJlYWRSb3V0aW5nRnJvbURpc2soYWNjb3VudCwgYnVja2V0TmFtZSkpO1xuICAgICAgICAgICAgICAgIGlmICghcGFyc2VkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7IC4uLmJhc2UsIGVycm9yOiBgTm8gcm91dGluZyBmaWxlICgke1JPVVRJTkdfRklMRX0pIGluIGFueSBvZiBpdHMgc3RvcmVzYCB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4geyAuLi5iYXNlLCBjb25maWc6IHsgcmVtb3RlQ29uZmlnOiBwYXJzZWQgfSB9O1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB7IC4uLmJhc2UsIGVycm9yOiBTdHJpbmcoKGUgYXMgRXJyb3IpLnN0YWNrID8/IGUpLnNsaWNlKDAsIDUwMCkgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSkpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICAgIC8vIFRoZSBwYXJ0cyBydW4gY29uY3VycmVudGx5LCBzbyB0aGVzZSBhcmUgc3VtbWVkIHdhbGwgdGltZXMgcGVyIHBhcnQsIG5vdCBhIGJyZWFrZG93biBvZiB0aGUgdG90YWxcbiAgICAgICAgbGV0IHBhcnRzID0gWy4uLnRpbWluZ3NdLm1hcCgoW25hbWUsIG1zXSkgPT4gYCR7bmFtZX0gJHttc31tc2ApLmpvaW4oXCIsIFwiKTtcbiAgICAgICAgY29uc29sZS5sb2coYGxpc3RBY2NvdW50QnVja2V0cygke2FjY291bnR9KSB0b29rICR7RGF0ZS5ub3coKSAtIHN0YXJ0fW1zIGZvciAke25hbWVzLmxlbmd0aH0gYnVja2V0czogJHtwYXJ0c31gKTtcbiAgICB9XG59XG5cbmV4cG9ydCB0eXBlIEJ1Y2tldFdyaXRlU3RhdHMgPSB7XG4gICAgLyoqIEV2ZXJ5IHNldCBjYWxsIHRoZSBidWNrZXQgYWNjZXB0ZWQgKi9cbiAgICBvcmlnaW5hbFdyaXRlczogbnVtYmVyO1xuICAgIG9yaWdpbmFsQnl0ZXM6IG51bWJlcjtcbiAgICAvKiogV2hhdCBhY3R1YWxseSByZWFjaGVkIHRoZSBzb3VyY2VzLiBGYXN0IHdyaXRlcyBjb2FsZXNjZSByZXBlYXRlZCB3cml0ZXMgdG8gdGhlIHNhbWUga2V5LCBzbyB0aGlzIGlzIGxvd2VyIHRoYW4gdGhlIG9yaWdpbmFsIGNvdW50cyAoYW5kIGlzIHdoYXQgdGhlIGRpc2sgYWN0dWFsbHkgZGlkKS4gKi9cbiAgICBmbHVzaGVkV3JpdGVzOiBudW1iZXI7XG4gICAgZmx1c2hlZEJ5dGVzOiBudW1iZXI7XG59O1xuZnVuY3Rpb24gZW1wdHlXcml0ZVN0YXRzKCk6IEJ1Y2tldFdyaXRlU3RhdHMge1xuICAgIHJldHVybiB7IG9yaWdpbmFsV3JpdGVzOiAwLCBvcmlnaW5hbEJ5dGVzOiAwLCBmbHVzaGVkV3JpdGVzOiAwLCBmbHVzaGVkQnl0ZXM6IDAgfTtcbn1cblxuLy8gSW4gbWVtb3J5IG9ubHk6IHRvdGFscyBzaW5jZSB0aGlzIHByb2Nlc3Mgc3RhcnRlZCAob3IgdGhlIGxhc3QgY2xlYXJXcml0ZVN0YXRzKS4gUGVyc2lzdGluZyB0aGVtIHRvIGRpc2sgd2FzIG1vcmUgbWFjaGluZXJ5IHRoYW4gdGhlIG51bWJlcnMgd2VyZSB3b3J0aC5cbmNvbnN0IHdyaXRlU3RhdHMgPSBuZXcgTWFwPHN0cmluZywgQnVja2V0V3JpdGVTdGF0cz4oKTtcblxuZnVuY3Rpb24gY291bnRCdWNrZXRXcml0ZShrZXk6IHN0cmluZywga2luZDogXCJvcmlnaW5hbFwiIHwgXCJmbHVzaGVkXCIsIGJ5dGVzOiBudW1iZXIpOiB2b2lkIHtcbiAgICBsZXQgc3RhdHMgPSB3cml0ZVN0YXRzLmdldChrZXkpO1xuICAgIGlmICghc3RhdHMpIHtcbiAgICAgICAgc3RhdHMgPSBlbXB0eVdyaXRlU3RhdHMoKTtcbiAgICAgICAgd3JpdGVTdGF0cy5zZXQoa2V5LCBzdGF0cyk7XG4gICAgfVxuICAgIGlmIChraW5kID09PSBcIm9yaWdpbmFsXCIpIHtcbiAgICAgICAgc3RhdHMub3JpZ2luYWxXcml0ZXMrKztcbiAgICAgICAgc3RhdHMub3JpZ2luYWxCeXRlcyArPSBieXRlcztcbiAgICB9IGVsc2Uge1xuICAgICAgICBzdGF0cy5mbHVzaGVkV3JpdGVzKys7XG4gICAgICAgIHN0YXRzLmZsdXNoZWRCeXRlcyArPSBieXRlcztcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGdldEJ1Y2tldFdyaXRlU3RhdHMoa2V5OiBzdHJpbmcpOiBCdWNrZXRXcml0ZVN0YXRzIHtcbiAgICByZXR1cm4gd3JpdGVTdGF0cy5nZXQoa2V5KSB8fCBlbXB0eVdyaXRlU3RhdHMoKTtcbn1cblxuLyoqIFplcm9lcyB0aGUgd3JpdGUgc3RhdGlzdGljcyBvZiBldmVyeSBidWNrZXQgaW4gdGhlIGFjY291bnQuICovXG5leHBvcnQgZnVuY3Rpb24gY2xlYXJBY2NvdW50V3JpdGVTdGF0cyhhY2NvdW50OiBzdHJpbmcpOiBudW1iZXIge1xuICAgIGxldCBwcmVmaXggPSBgJHthY2NvdW50fS9gO1xuICAgIGxldCBjbGVhcmVkID0gMDtcbiAgICBmb3IgKGxldCBrZXkgb2YgWy4uLndyaXRlU3RhdHMua2V5cygpXSkge1xuICAgICAgICBpZiAoIWtleS5zdGFydHNXaXRoKHByZWZpeCkpIGNvbnRpbnVlO1xuICAgICAgICB3cml0ZVN0YXRzLmRlbGV0ZShrZXkpO1xuICAgICAgICBjbGVhcmVkKys7XG4gICAgfVxuICAgIGNvbnNvbGUubG9nKGBDbGVhcmVkIHRoZSB3cml0ZSBzdGF0aXN0aWNzIG9mICR7Y2xlYXJlZH0gYnVja2V0cyBpbiBhY2NvdW50ICR7YWNjb3VudH1gKTtcbiAgICByZXR1cm4gY2xlYXJlZDtcbn1cbiJdfQ==
390
- /* _JS_SOURCE_HASH = "30e439e150cb478d27dce6c02f954eb14cc1e05bb1d8589b039ef177b3ae996e"; */
259
+ exports.debugListAccountBuckets = debugListAccountBuckets;
260
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RvcmFnZVNlcnZlclN0YXRlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic3RvcmFnZVNlcnZlclN0YXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDJDQUF3QztBQUl4QyxpREFBd0c7QUFDeEcsaURBQXNFO0FBQ3RFLDJEQUE4RDtBQUM5RCxpREFBcUQ7QUFDckQsNkNBQXFEO0FBQ3JELDZDQUFrSjtBQUNsSixxRUFBdUY7QUFDdkYsMkNBQTJDO0FBQzNDLCtDQUF3RjtBQUV4Rjs7Ozs7R0FLRztBQUVIOzs7O0dBSUc7QUFDSCxNQUFNLE1BQU0sR0FBRyxJQUFJLEdBQUcsRUFBcUIsQ0FBQztBQUM1QywrTUFBK007QUFDL00sTUFBTSxZQUFZLEdBQUcsSUFBSSxHQUFHLEVBQWtDLENBQUM7QUFFL0QsU0FBZ0IsUUFBUSxDQUFDLE9BQWUsRUFBRSxVQUFrQixFQUFFLElBQVk7SUFDdEUsOEdBQThHO0lBQzlHLElBQUEsa0NBQXFCLEVBQUMsSUFBSSxDQUFDLENBQUM7SUFDNUIsSUFBSSxNQUFNLEdBQUcsSUFBQSw0QkFBZSxFQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFDeEQsSUFBSSxRQUFRLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNsQyxJQUFJLFFBQVE7UUFBRSxPQUFPLFFBQVEsQ0FBQztJQUM5QixPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxjQUFjLE9BQU8sSUFBSSxVQUFVLFlBQVksTUFBTSxtREFBbUQsQ0FBQyxDQUFDO0lBQzNKLElBQUksS0FBSyxHQUFHLElBQUkscUJBQVMsQ0FBQyxNQUFNLEVBQUUsSUFBSSxFQUFFO1FBQ3BDLG1FQUFtRTtRQUNuRSxNQUFNLEVBQUUsTUFBTSxDQUFDLEVBQUUsQ0FBQyxJQUFBLHdCQUFZLEVBQUMsTUFBTSxFQUFFLE9BQU8sRUFBRSxVQUFVLENBQUM7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QUUsS0FBSyxFQUFFLG9CQUFvQiwyQkFBWSx3QkFBd0IsRUFBRSxDQUFDO2dCQUN4RixDQUFDO2dCQUNELE9BQU8sRUFBRSxHQUFHLElBQUksRUFBRSxNQUFNLEVBQUUsRUFBRSxZQUFZLEVBQUUsT0FBTyxFQUFFLEVBQUUsQ0FBQztZQUMxRCxDQUFDO1lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztnQkFDVCxPQUFPLEVBQUUsR0FBRyxJQUFJLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxNQUFDLENBQVcsQ0FBQyxLQUFLLG1DQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUM3RSxDQUFDO1FBQ0wsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNSLENBQUM7WUFBUyxDQUFDO1FBQ1AsT0FBTyxDQUFDLEdBQUcsQ0FBQywyQkFBMkIsT0FBTyxVQUFVLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxLQUFLLFVBQVUsS0FBSyxDQUFDLE1BQU0sVUFBVSxDQUFDLENBQUM7SUFDaEgsQ0FBQztBQUNMLENBQUM7QUFyQ0QsMERBcUNDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQmxvYlN0b3JlIH0gZnJvbSBcIi4vYmxvYlN0b3JlXCI7XG5pbXBvcnQge1xuICAgIFJlbW90ZUNvbmZpZywgU291cmNlQ29uZmlnLCBJQXJjaGl2ZXMsIEFyY2hpdmVzQ29uZmlnLCBBcmNoaXZlc1N5bmNTdGF0dXMsIFN5bmNBY3Rpdml0eSxcbn0gZnJvbSBcIi4uL0lBcmNoaXZlc1wiO1xuaW1wb3J0IHsgUk9VVElOR19GSUxFLCBwYXJzZVJvdXRpbmdEYXRhLCBzZXJpYWxpemVSZW1vdGVDb25maWcsIG5vcm1hbGl6ZVNvdXJjZSB9IGZyb20gXCIuL3JlbW90ZUNvbmZpZ1wiO1xuaW1wb3J0IHsgY3JlYXRlU3RvcmVTb3VyY2UsIGFwcGx5U291cmNlQ29uZmlnIH0gZnJvbSBcIi4vc3RvcmVTb3VyY2VzXCI7XG5pbXBvcnQgeyBicm9hZGNhc3RSb3V0aW5nQ2hhbmdlZCB9IGZyb20gXCIuL3N0b3JhZ2VDb250cm9sbGVyXCI7XG5pbXBvcnQgeyBhc3NlcnRXcml0ZXNBbGxvd2VkIH0gZnJvbSBcIi4vc2VydmVyQ29uZmlnXCI7XG5pbXBvcnQgeyBhc3NlcnRWYWxpZFNvdXJjZU5hbWUgfSBmcm9tIFwiLi92YWxpZGF0aW9uXCI7XG5pbXBvcnQgeyBnZXRCdWNrZXRGb2xkZXIsIGxpc3RBY2NvdW50U3RvcmVGb2xkZXJzLCBsaXN0QnVja2V0U3RvcmVGb2xkZXJzLCByZWFkUm91dGluZ0Zyb21EaXNrLCBnZXREaXNrSW5mbywgQnVja2V0RGlza0luZm8gfSBmcm9tIFwiLi9idWNrZXREaXNrXCI7XG5pbXBvcnQgeyBzY2hlZHVsZUJvdW5kYXJ5V29yaywgcmVpbmplY3RJbnRlcm1lZGlhdGVzIH0gZnJvbSBcIi4vaW50ZXJtZWRpYXRlTWFuYWdlbWVudFwiO1xuaW1wb3J0IHsgaXNTZWxmU291cmNlIH0gZnJvbSBcIi4vc3RvcmVQbGFuXCI7XG5pbXBvcnQgeyBjb3VudEJ1Y2tldFdyaXRlLCBnZXRCdWNrZXRXcml0ZVN0YXRzLCBCdWNrZXRXcml0ZVN0YXRzIH0gZnJvbSBcIi4vYWNjZXNzU3RhdHNcIjtcblxuLyoqXG4gKiBXaGF0IHRoaXMgc2VydmVyIEhBUzogdGhlIHN0b3JlcywgYnkgbmFtZSAoZ2V0U3RvcmUpIC0gbWFkZSBvbmNlLCBzZWxmLWNvbmZpZ3VyaW5nIGZyb20gdGhlcmUgLVxuICogYW5kIHRoZSB0aHJlZSBlbnRyeSBwb2ludHMgYSByZXF1ZXN0IHJlc29sdmVzIHRocm91Z2ggKGZpbmRCdWNrZXRTdG9yZSwgcmVhZEJ1Y2tldEludGVybmFsLFxuICogd3JpdGVSb3V0aW5nQ29uZmlnKS4gVGhlcmUgaXMgbm8gY2FjaGVkIGJ1Y2tldCBzdGF0ZTogYSBidWNrZXQgaXMgbm90aGluZyBidXQgdGhlIHN0b3JlcyB3aG9zZVxuICogZm9sZGVycyBzaGFyZSBpdHMgbmFtZSwgbGlzdGVkIG9mZiB0aGUgZGlzayB3aGVuIHNvbWV0aGluZyBnZW51aW5lbHkgbmVlZHMgYWxsIG9mIHRoZW0uXG4gKi9cblxuLyoqXG4gKiBFdmVyeSBzdG9yZSB0aGlzIHByb2Nlc3MgcnVucywgYnkgZm9sZGVyIC0gd2hpY2ggSVMgdGhlIHN0b3JlJ3MgaWRlbnRpdHk6IGFjY291bnQsIG5hbWUsIGJ1Y2tldC5cbiAqIEEgc3RvcmUgaXMgbWFkZSBvbmNlLCBjb25maWd1cmVzIGl0c2VsZiBmcm9tIHRoZSByb3V0aW5nIGNvbmZpZyBpdCBob2xkcywgYW5kIHN0YXlzOyBub3RoaW5nIGhlcmVcbiAqIGRlY2lkZXMgd2hhdCBpdCBpcywgb25seSB0aGF0IGl0IGV4aXN0cy5cbiAqL1xuY29uc3Qgc3RvcmVzID0gbmV3IE1hcDxzdHJpbmcsIEJsb2JTdG9yZT4oKTtcbi8vIFRoZSBvcGVuZWQgc3RvcmVzIG9mIGVhY2ggYCR7YWNjb3VudH0vJHtidWNrZXROYW1lfWAsIGJ5IG5hbWUgLSB3aGljaCBidWNrZXRzIGFyZSBBQ1RJVkUgKHNvbWV0aGluZyB0b3VjaGVkIHRoZW0pLCBmb3IgZGVwbG95IGhhbmRvZmZzIGFuZCB0aGUgZGVidWcgcGFnZXMuIFB1cmVseSBhIHJlZ2lzdHJ5IG9mIHdoYXQgZ2V0U3RvcmUgYWxyZWFkeSBtYWRlLlxuY29uc3QgYWN0aXZlU3RvcmVzID0gbmV3IE1hcDxzdHJpbmcsIE1hcDxzdHJpbmcsIEJsb2JTdG9yZT4+KCk7XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTdG9yZShhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZywgbmFtZTogc3RyaW5nKTogQmxvYlN0b3JlIHtcbiAgICAvLyBUaGUgb25lIHBsYWNlIGEgbmFtZSBiZWNvbWVzIGEgZm9sZGVyLCBzbyB0aGUgb25lIHBsYWNlIGl0IGlzIHZhbGlkYXRlZCAoaXQgY2FuIGNvbWUgc3RyYWlnaHQgb2ZmIHRoZSB3aXJlKVxuICAgIGFzc2VydFZhbGlkU291cmNlTmFtZShuYW1lKTtcbiAgICBsZXQgZm9sZGVyID0gZ2V0QnVja2V0Rm9sZGVyKG5hbWUsIGFjY291bnQsIGJ1Y2tldE5hbWUpO1xuICAgIGxldCBleGlzdGluZyA9IHN0b3Jlcy5nZXQoZm9sZGVyKTtcbiAgICBpZiAoZXhpc3RpbmcpIHJldHVybiBleGlzdGluZztcbiAgICBjb25zb2xlLmxvZyhgT3BlbmluZyBzdG9yZSAke0pTT04uc3RyaW5naWZ5KG5hbWUpfSBvZiBidWNrZXQgJHthY2NvdW50fS8ke2J1Y2tldE5hbWV9IChmb2xkZXIgJHtmb2xkZXJ9KSAtIGNyZWF0ZWQgb24gdGhpcyBmaXJzdCB1c2UgaWYgaXQgbmV2ZXIgZXhpc3RlZGApO1xuICAgIGxldCBzdG9yZSA9IG5ldyBCbG9iU3RvcmUoZm9sZGVyLCBuYW1lLCB7XG4gICAgICAgIC8vIFdoaWNoIGVudHJpZXMgaW4gSVRTIHJvdXRpbmcgY29uZmlnIGFyZSB0aGlzIHNlcnZlcidzIGNvcHkgb2YgaXRcbiAgICAgICAgaXNTZWxmOiBzb3VyY2UgPT4gaXNTZWxmU291cmNlKHNvdXJjZSwgYWNjb3VudCwgYnVja2V0TmFtZSksXG4gICAgICAgIGNyZWF0ZVNvdXJjZTogY29uZmlnID0+IGNyZWF0ZVN0b3JlU291cmNlKHsgc291cmNlQ29uZmlnOiBjb25maWcuc291cmNlQ29uZmlnLCBmb2xkZXIsIHdyaXRlRGVsYXk6IGNvbmZpZy53cml0ZURlbGF5IH0pLFxuICAgICAgICBhcHBseVNvdXJjZTogKHNvdXJjZSwgc291cmNlQ29uZmlnLCB3cml0ZURlbGF5KSA9PiBhcHBseVNvdXJjZUNvbmZpZyhzb3VyY2UsIHNvdXJjZUNvbmZpZywgd3JpdGVEZWxheSksXG4gICAgICAgIG9uV3JpdGVDb3VudGVkOiAoa2luZCwgYnl0ZXMpID0+IGNvdW50QnVja2V0V3JpdGUoYCR7YWNjb3VudH0vJHtidWNrZXROYW1lfWAsIGtpbmQsIGJ5dGVzKSxcbiAgICAgICAgcmVzb2x2ZVNvdXJjZVVybDogcmVzb2x2ZVNvdXJjZUFyY2hpdmVzLFxuICAgICAgICAvLyBUaGUgc3RvcmUgaXMgdGhlIG9uZSB0aGF0IGtub3dzIHdoZW4gYSBjb25maWcgbGFuZGVkLCBhbmQgYSBjb25maWcgd2l0aCB1cGNvbWluZyB3aW5kb3dzIGlzIHdoYXQgYm91bmRhcnkgc2NhbnMgYXJlIGFybWVkIGZyb21cbiAgICAgICAgb25Sb3V0aW5nQXBwbGllZDogcm91dGluZyA9PiBzY2hlZHVsZUJvdW5kYXJ5V29yayhhY2NvdW50LCBidWNrZXROYW1lLCByb3V0aW5nKSxcbiAgICB9KTtcbiAgICBzdG9yZXMuc2V0KGZvbGRlciwgc3RvcmUpO1xuICAgIGxldCBrZXkgPSBgJHthY2NvdW50fS8ke2J1Y2tldE5hbWV9YDtcbiAgICBsZXQgYnlOYW1lID0gYWN0aXZlU3RvcmVzLmdldChrZXkpO1xuICAgIGlmICghYnlOYW1lKSB7XG4gICAgICAgIGJ5TmFtZSA9IG5ldyBNYXAoKTtcbiAgICAgICAgYWN0aXZlU3RvcmVzLnNldChrZXksIGJ5TmFtZSk7XG4gICAgfVxuICAgIGJ5TmFtZS5zZXQobmFtZSwgc3RvcmUpO1xuICAgIC8vIExhenkgaW5pdCB3b3VsZCBsZWF2ZSBhIHN0b3JlIG5vdGhpbmcgaGFzIHRvdWNoZWQgc2l0dGluZyBpbmVydCAtIG5vIGluZGV4IGxvYWRlZCwgbm8gY29uZmlnIGFwcGxpZWQsIG5vdGhpbmcgc3luY2hyb25pemluZyAtIHdoaWxlIGl0cyBmb2xkZXIgaXMgZnVsbCBvZiBmaWxlc1xuICAgIHZvaWQgc3RvcmUuaW5pdCgpLmNhdGNoKChlOiBFcnJvcikgPT4gY29uc29sZS5lcnJvcihgSW5pdGlhbGl6aW5nIHN0b3JlICR7SlNPTi5zdHJpbmdpZnkobmFtZSl9IG9mIGJ1Y2tldCAke2FjY291bnR9LyR7YnVja2V0TmFtZX0gZmFpbGVkOiAke2Uuc3RhY2sgPz8gZX1gKSk7XG4gICAgcmV0dXJuIHN0b3JlO1xufVxuXG4vKiogVGhlIHN0b3JlIHNlcnZpbmcgYSByZXF1ZXN0OiB0aGUgb25lIHRoZSBjbGllbnQncyBzZWxlY3RlZCBlbnRyeSBOQU1FUy4gQWNjb3VudCwgbmFtZSwgYW5kIGJ1Y2tldCBBUkUgdGhlIGZvbGRlciwgc28gdGhpcyBpcyBhIGRpcmVjdCBsb29rdXAsIG5ldmVyIGEgc2VhcmNoIG9mIHdoYXQgZXhpc3RzIC0gYW5kIGEgbmFtZSB0aGlzIHNlcnZlciBoYXMgbmV2ZXIgc2VlbiBpcyBDUkVBVEVELCBuZXZlciByZWplY3RlZCwgYmVjYXVzZSBhc2tpbmcgZm9yIGEgbmFtZSBpcyB0aGUgaW5zdHJ1Y3Rpb24gdG8gaGF2ZSB0aGF0IHN0b3JlIChvbmUgbmFtZSwgb25lIGZvbGRlciwgb25lIGluZGV4OyBpdCBjb25maWd1cmVzIGl0c2VsZiBvbmNlIHRoZSByb3V0aW5nIGNvbmZpZyBsYW5kcyBpbiBpdCkuIE5vdGhpbmcgZWxzZSBhYm91dCB0aGUgcmVxdWVzdCBpcyBjb21wYXJlZCAtIG5vdCB0aGUgd2luZG93LCBub3QgdGhlIHJvdXRlLCBub3QgdGhlIGZsYWdzIC0gd2hpY2ggaXMgdGhlIHdob2xlIHBvaW50IG9mIG5hbWluZyBpdDogYSBjbGllbnQgYSBjb25maWcgdmVyc2lvbiBiZWhpbmQgb24gc29tZSBmbGFnIHN0aWxsIHJlYWNoZXMgdGhlIHJpZ2h0IHN0b3JlLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZpbmRCdWNrZXRTdG9yZShhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZywgc291cmNlQ29uZmlnOiBTb3VyY2VDb25maWcgfCB1bmRlZmluZWQpOiBCbG9iU3RvcmUge1xuICAgIGlmICghc291cmNlQ29uZmlnKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgTm8gcmVtb3RlIHNvdXJjZSBjb25maWd1cmF0aW9uIHdhcyBwcm92aWRlZCBmb3IgYnVja2V0ICR7YWNjb3VudH0vJHtidWNrZXROYW1lfTogZXZlcnkgcmVxdWVzdCBtdXN0IHNheSB3aGljaCBjb25maWd1cmVkIHNvdXJjZSBpdCBzZWxlY3RlZGApO1xuICAgIH1cbiAgICByZXR1cm4gZ2V0U3RvcmUoYWNjb3VudCwgYnVja2V0TmFtZSwgc291cmNlQ29uZmlnLm5hbWUpO1xufVxuXG4vKiogVGhlIHN0b3JlcyBvZiBhIGJ1Y2tldCBhcyB0aGUgRElTSyByZWNvcmRzIHRoZW0gKGEgYnVja2V0IGlzIG5vdGhpbmcgbW9yZSB0aGFuIHRoZSBzdG9yZSBmb2xkZXJzIHNoYXJpbmcgaXRzIG5hbWUpLCBvcGVuZWQgLSBzbyB0aGUgb25lcyB0aGF0IHdlcmVuJ3QgcnVubmluZyB5ZXQgc3RhcnQgc3luY2hyb25pemluZy4gRW1wdHkgd2hlbiB0aGUgYnVja2V0IGRvZXMgbm90IGV4aXN0IGhlcmUuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0QnVja2V0U3RvcmVzKGFjY291bnQ6IHN0cmluZywgYnVja2V0TmFtZTogc3RyaW5nKTogUHJvbWlzZTx7IG5hbWU6IHN0cmluZzsgc3RvcmU6IEJsb2JTdG9yZSB9W10+IHtcbiAgICBsZXQgZm9sZGVycyA9IGF3YWl0IGxpc3RCdWNrZXRTdG9yZUZvbGRlcnMoYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgcmV0dXJuIGZvbGRlcnMubWFwKHggPT4gKHsgbmFtZTogeC5uYW1lLCBzdG9yZTogZ2V0U3RvcmUoYWNjb3VudCwgYnVja2V0TmFtZSwgeC5uYW1lKSB9KSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlcXVpcmVCdWNrZXRTdG9yZXMoYWNjb3VudDogc3RyaW5nLCBidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPHsgbmFtZTogc3RyaW5nOyBzdG9yZTogQmxvYlN0b3JlIH1bXT4ge1xuICAgIGxldCBsaXN0ID0gYXdhaXQgZ2V0QnVja2V0U3RvcmVzKGFjY291bnQsIGJ1Y2tldE5hbWUpO1xuICAgIGlmICghbGlzdC5sZW5ndGgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBCdWNrZXQgJHthY2NvdW50fS8ke2J1Y2tldE5hbWV9IGRvZXMgbm90IGV4aXN0IG9uIHRoaXMgc2VydmVyLiBXcml0ZSBpdHMgcm91dGluZyBjb25maWcgdG8gJHtKU09OLnN0cmluZ2lmeShST1VUSU5HX0ZJTEUpfSB0byBjcmVhdGUgaXQuYCk7XG4gICAgfVxuICAgIHJldHVybiBsaXN0O1xufVxuXG4vKiogSW50ZXJuYWwgKHN0b3JlLXRvLXN0b3JlKSByZWFkcyBza2lwIHN0b3JlIHNlbGVjdGlvbiBlbnRpcmVseTogdGhlIGNhbGxlciBpcyBhbm90aGVyIHN0b3JlIHdob3NlIGluZGV4IHNheXMgdGhpcyBNQUNISU5FIGhvbGRzIHRoZSBieXRlcyAtIHRoZSBwZXJzaXN0ZWQgaG9sZGVyIGlkZW50aXR5IGlzIGp1c3QgYSBVUkwsIHdoaWNoIGNhbm5vdCBuYW1lIGEgc3RvcmUuIFdoaWNoZXZlciBzdG9yZSdzIGZvbGRlciBoYXMgdGhlIG5ld2VzdCBjb3B5IGFuc3dlcnMuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZEJ1Y2tldEludGVybmFsKGFjY291bnQ6IHN0cmluZywgYnVja2V0TmFtZTogc3RyaW5nLCBjb25maWc6IHsgcGF0aDogc3RyaW5nOyByYW5nZT86IHsgc3RhcnQ6IG51bWJlcjsgZW5kOiBudW1iZXIgfTsgaW5jbHVkZVRvbWJzdG9uZXM/OiBib29sZWFuIH0pOiBQcm9taXNlPHsgZGF0YTogQnVmZmVyOyB3cml0ZVRpbWU6IG51bWJlcjsgc2l6ZTogbnVtYmVyIH0gfCB1bmRlZmluZWQ+IHtcbiAgICBsZXQgYnVja2V0U3RvcmVzID0gYXdhaXQgcmVxdWlyZUJ1Y2tldFN0b3JlcyhhY2NvdW50LCBidWNrZXROYW1lKTtcbiAgICBsZXQgcmVzdWx0cyA9IGF3YWl0IFByb21pc2UuYWxsKGJ1Y2tldFN0b3Jlcy5tYXAocyA9PiBzLnN0b3JlLmdldDIoeyBwYXRoOiBjb25maWcucGF0aCwgcmFuZ2U6IGNvbmZpZy5yYW5nZSwgaW5jbHVkZVRvbWJzdG9uZXM6IGNvbmZpZy5pbmNsdWRlVG9tYnN0b25lcywgaW50ZXJuYWw6IHRydWUgfSkpKTtcbiAgICBsZXQgYmVzdDogeyBkYXRhOiBCdWZmZXI7IHdyaXRlVGltZTogbnVtYmVyOyBzaXplOiBudW1iZXIgfSB8IHVuZGVmaW5lZDtcbiAgICBmb3IgKGxldCByZXN1bHQgb2YgcmVzdWx0cykge1xuICAgICAgICBpZiAocmVzdWx0ICYmICghYmVzdCB8fCByZXN1bHQud3JpdGVUaW1lID4gYmVzdC53cml0ZVRpbWUpKSB7XG4gICAgICAgICAgICBiZXN0ID0gcmVzdWx0O1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBiZXN0O1xufVxuXG5mdW5jdGlvbiBhZ2dyZWdhdGVBcmNoaXZlc0NvbmZpZyhidWNrZXRTdG9yZXM6IEJsb2JTdG9yZVtdLCByb3V0aW5nOiBSZW1vdGVDb25maWcgfCB1bmRlZmluZWQpOiBBcmNoaXZlc0NvbmZpZyB7XG4gICAgbGV0IGluZGV4ID0geyBmaWxlQ291bnQ6IDAsIGJ5dGVDb3VudDogMCB9O1xuICAgIGxldCBpbmRleFNvdXJjZXM6IHsgZGVidWdOYW1lOiBzdHJpbmc7IGZpbGVDb3VudDogbnVtYmVyOyBieXRlQ291bnQ6IG51bWJlciB9W10gPSBbXTtcbiAgICBsZXQgc3luY2luZzogU3luY0FjdGl2aXR5W10gPSBbXTtcbiAgICBsZXQgcmVhZGVyRGlza0xpbWl0OiBudW1iZXIgfCB1bmRlZmluZWQ7XG4gICAgZm9yIChsZXQgc3RvcmUgb2YgYnVja2V0U3RvcmVzKSB7XG4gICAgICAgIGxldCBwcm9ncmVzcyA9IHN0b3JlLmdldFN5bmNQcm9ncmVzcygpO1xuICAgICAgICBpbmRleC5maWxlQ291bnQgKz0gcHJvZ3Jlc3MuaW5kZXguZmlsZUNvdW50O1xuICAgICAgICBpbmRleC5ieXRlQ291bnQgKz0gcHJvZ3Jlc3MuaW5kZXguYnl0ZUNvdW50O1xuICAgICAgICBpbmRleFNvdXJjZXMucHVzaCguLi5wcm9ncmVzcy5zb3VyY2VzKTtcbiAgICAgICAgc3luY2luZy5wdXNoKC4uLnByb2dyZXNzLnN5bmNpbmcpO1xuICAgICAgICByZWFkZXJEaXNrTGltaXQgPSByZWFkZXJEaXNrTGltaXQgfHwgcHJvZ3Jlc3MucmVhZGVyRGlza0xpbWl0O1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICAvLyBFdmVyeSBzdG9yZSBpcyBpbmRleC1iYWNrZWQsIHNvIHRoZSBjaGFuZ2UgZmVlZCBpcyBhbHdheXMgbmF0aXZlXG4gICAgICAgIHN1cHBvcnRzQ2hhbmdlc0FmdGVyOiB0cnVlLFxuICAgICAgICByZW1vdGVDb25maWc6IHJvdXRpbmcsXG4gICAgICAgIGluZGV4LFxuICAgICAgICBpbmRleFNvdXJjZXMsXG4gICAgICAgIHJlYWRlckRpc2tMaW1pdCxcbiAgICAgICAgc3luY2luZyxcbiAgICB9O1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0QnVja2V0QXJjaGl2ZXNDb25maWcoYWNjb3VudDogc3RyaW5nLCBidWNrZXROYW1lOiBzdHJpbmcpOiBQcm9taXNlPEFyY2hpdmVzQ29uZmlnPiB7XG4gICAgbGV0IGJ1Y2tldFN0b3JlcyA9IGF3YWl0IHJlcXVpcmVCdWNrZXRTdG9yZXMoYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgbGV0IHJvdXRpbmcgPSBhd2FpdCByZWFkUm91dGluZ0Zyb21EaXNrKGFjY291bnQsIGJ1Y2tldE5hbWUpO1xuICAgIHJldHVybiBhZ2dyZWdhdGVBcmNoaXZlc0NvbmZpZyhidWNrZXRTdG9yZXMubWFwKHggPT4geC5zdG9yZSksIHJvdXRpbmcpO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYnVja2V0U3luY1N0YXR1cyhhY2NvdW50OiBzdHJpbmcsIGJ1Y2tldE5hbWU6IHN0cmluZyk6IFByb21pc2U8QXJjaGl2ZXNTeW5jU3RhdHVzPiB7XG4gICAgbGV0IGJ1Y2tldFN0b3JlcyA9IGF3YWl0IHJlcXVpcmVCdWNrZXRTdG9yZXMoYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgbGV0IHN0YXR1c2VzID0gYXdhaXQgUHJvbWlzZS5hbGwoYnVja2V0U3RvcmVzLm1hcChzID0+IHMuc3RvcmUuZ2V0U3luY1N0YXR1cygpKSk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgYWxsU2NhbnNDb21wbGV0ZTogc3RhdHVzZXMuZXZlcnkoeCA9PiB4LmFsbFNjYW5zQ29tcGxldGUpLFxuICAgICAgICBpbmRleFNpemU6IHN0YXR1c2VzLnJlZHVjZSgoc3VtLCB4KSA9PiBzdW0gKyB4LmluZGV4U2l6ZSwgMCksXG4gICAgICAgIHNvdXJjZXM6IHN0YXR1c2VzLmZsYXRNYXAoeCA9PiB4LnNvdXJjZXMpLFxuICAgIH07XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkZWJ1Z0J1Y2tldEluZGV4VG90YWxzKGFjY291bnQ6IHN0cmluZywgYnVja2V0TmFtZTogc3RyaW5nKTogUHJvbWlzZTx7IGZpbGVDb3VudDogbnVtYmVyOyBieXRlQ291bnQ6IG51bWJlcjsgc291cmNlczogeyBkZWJ1Z05hbWU6IHN0cmluZzsgZmlsZUNvdW50OiBudW1iZXI7IGJ5dGVDb3VudDogbnVtYmVyIH1bXSB9PiB7XG4gICAgbGV0IGJ1Y2tldFN0b3JlcyA9IGF3YWl0IHJlcXVpcmVCdWNrZXRTdG9yZXMoYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgbGV0IHRvdGFscyA9IGF3YWl0IFByb21pc2UuYWxsKGJ1Y2tldFN0b3Jlcy5tYXAocyA9PiBzLnN0b3JlLmNvbXB1dGVJbmRleFRvdGFscygpKSk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZmlsZUNvdW50OiB0b3RhbHMucmVkdWNlKChzdW0sIHgpID0+IHN1bSArIHguZmlsZUNvdW50LCAwKSxcbiAgICAgICAgYnl0ZUNvdW50OiB0b3RhbHMucmVkdWNlKChzdW0sIHgpID0+IHN1bSArIHguYnl0ZUNvdW50LCAwKSxcbiAgICAgICAgc291cmNlczogdG90YWxzLmZsYXRNYXAoeCA9PiB4LnNvdXJjZXMpLFxuICAgIH07XG59XG5cbmNvbnN0IHJlc29sdmVkU291cmNlQXJjaGl2ZXMgPSBuZXcgTWFwPHN0cmluZywgSUFyY2hpdmVzPigpO1xuLyoqIEEgY2FjaGVkIElBcmNoaXZlcyBmb3IgYSBwZXJzaXN0ZWQgc291cmNlIGlkZW50aXR5OiBhIHJvdXRpbmcgVVJMIChob3N0ZWQvYmFja2JsYXplKSBvciBhIGRpc2sgZm9sZGVyIHBhdGggLSB0aGUgZm9ybSBCbG9iU3RvcmUncyBzb3VyY2VzIGxpc3Qgc3RvcmVzLiBDb25maWd1cmF0aW9uICh2YWxpZCB3aW5kb3dzLCByb3V0ZXMpIGRlY2lkZXMgV0hFTiBhIHNvdXJjZSBzaG91bGQgYmUgdXNlZDsgZm9yIHJlYWRpbmcgYnl0ZXMgdGhlIGluZGV4IHNheXMgYSBzb3VyY2UgaG9sZHMsIHRoZSBVUkwgYWxvbmUgaXMgZW5vdWdoIC0gZXZlbiBmb3Igc291cmNlcyBubyBsb25nZXIgaW4gYW55IGNvbmZpZy4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlU291cmNlQXJjaGl2ZXModXJsOiBzdHJpbmcpOiBJQXJjaGl2ZXMge1xuICAgIGxldCBleGlzdGluZyA9IHJlc29sdmVkU291cmNlQXJjaGl2ZXMuZ2V0KHVybCk7XG4gICAgaWYgKGV4aXN0aW5nKSByZXR1cm4gZXhpc3Rpbmc7XG4gICAgbGV0IHNvdXJjZUNvbmZpZzogU291cmNlQ29uZmlnIHwgdW5kZWZpbmVkO1xuICAgIGlmICh1cmwuc3RhcnRzV2l0aChcImh0dHBzOi8vXCIpKSB7XG4gICAgICAgIC8vIFRoZSBjb25maWcgaXMgZmFicmljYXRlZCBmcm9tIHRoZSBiYXJlIFVSTCBhbmQgY2FuIG5ldmVyIGV4YWN0LW1hdGNoIGEgc2VydmVyJ3MgZW50cmllcyAtIHdoaWNoIGlzIGZpbmUsIGJlY2F1c2UgaG9sZGVyIHJlYWRzIGFyZSBpbnRlcm5hbCByZWFkcywgYW5kIGludGVybmFsIHJlYWRzIG5ldmVyIHNlbGVjdCBhIHN0b3JlIChzZWUgcmVhZEJ1Y2tldEludGVybmFsKVxuICAgICAgICBzb3VyY2VDb25maWcgPSBub3JtYWxpemVTb3VyY2UodXJsKTtcbiAgICB9XG4gICAgbGV0IGFyY2hpdmVzID0gY3JlYXRlU3RvcmVTb3VyY2UoeyBzb3VyY2VDb25maWcsIGZvbGRlcjogdXJsIH0pO1xuICAgIHJlc29sdmVkU291cmNlQXJjaGl2ZXMuc2V0KHVybCwgYXJjaGl2ZXMpO1xuICAgIHJldHVybiBhcmNoaXZlcztcbn1cblxuLyoqXG4gKiBXcml0aW5nIHRoZSByb3V0aW5nIGNvbmZpZyBpcyBhIHdyaXRlIGxpa2UgYW55IG90aGVyOiBpdCBnb2VzIGludG8gYSBzdG9yZSwgYW5kIHRoZSBzdG9yZSBhcHBsaWVzXG4gKiBpdCB0byBpdHNlbGYgYW5kIGxldHMgaXRzIHBlZXJzIHB1bGwgaXQuIFRoZSBvbmx5IHRoaW5nIHRoYXQgaGFwcGVucyBoZXJlIGlzIHBpY2tpbmcgV0hJQ0ggc3RvcmUsXG4gKiBiZWNhdXNlIHRoZSB3cml0ZXIgbmFtZXMgYSBzb3VyY2UgYW5kIGEgc291cmNlIG5hbWVzIGEgc3RvcmUuXG4gKlxuICogSW4tZmxpZ2h0IHN3aXRjaG92ZXIgd2luZG93cyBhcmUgcmUtaW5qZWN0ZWQgZmlyc3QgKHNlZSBpbnRlcm1lZGlhdGVNYW5hZ2VtZW50KTogYW4gb3BlcmF0b3Inc1xuICogY29uZmlnIGtub3dzIG5vdGhpbmcgYWJvdXQgYSBzd2l0Y2hvdmVyIHRoYXQgaXMgaGFwcGVuaW5nIHJpZ2h0IG5vdywgYW5kIHdyaXRpbmcgaXQgYXMtaXMgd291bGRcbiAqIGNhbmNlbCBpdCBtaWQtZmxpZ2h0LlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd3JpdGVSb3V0aW5nQ29uZmlnKGFjY291bnQ6IHN0cmluZywgYnVja2V0TmFtZTogc3RyaW5nLCBuYW1lOiBzdHJpbmcsIGRhdGE6IEJ1ZmZlciwgY29uZmlnPzogeyBsYXN0TW9kaWZpZWQ/OiBudW1iZXIgfSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGFzc2VydFdyaXRlc0FsbG93ZWQoKTtcbiAgICBsZXQgc3RvcmUgPSBnZXRTdG9yZShhY2NvdW50LCBidWNrZXROYW1lLCBuYW1lKTtcbiAgICBsZXQgaW5jb21pbmcgPSBwYXJzZVJvdXRpbmdEYXRhKGRhdGEpO1xuICAgIGxldCBjdXJyZW50ID0gYXdhaXQgcmVhZFJvdXRpbmdGcm9tRGlzayhhY2NvdW50LCBidWNrZXROYW1lKTtcbiAgICBsZXQgc3RvcmVkID0gcmVpbmplY3RJbnRlcm1lZGlhdGVzKGN1cnJlbnQsIGluY29taW5nKTtcbiAgICBhd2FpdCBzdG9yZS5zZXQoeyBwYXRoOiBST1VUSU5HX0ZJTEUsIGRhdGE6IEJ1ZmZlci5mcm9tKHNlcmlhbGl6ZVJlbW90ZUNvbmZpZyhzdG9yZWQpKSwgbGFzdE1vZGlmaWVkOiBjb25maWc/Lmxhc3RNb2RpZmllZCB9KTtcbiAgICBicm9hZGNhc3RSb3V0aW5nQ2hhbmdlZCgpO1xufVxuXG4vKiogV2hpY2ggYnVja2V0cyB0aGlzIHByb2Nlc3MgY3VycmVudGx5IGhhcyBhY3RpdmUgKHNvbWUgc3RvcmUgb2YgdGhlaXJzIHdhcyBvcGVuZWQpIC0gd2hhdCBhIGRlcGxveSBzdWNjZXNzb3IgYXNrcyBpdHMgcHJlZGVjZXNzb3IgZm9yLCBzbyBpdCBhY3RpdmF0ZXMgZXhhY3RseSB0aGUgYnVja2V0cyB0aGF0IGFyZSBhY3R1YWxseSBpbiB1c2UuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0QWN0aXZlQnVja2V0S2V5cygpOiB7IGFjY291bnQ6IHN0cmluZzsgYnVja2V0TmFtZTogc3RyaW5nIH1bXSB7XG4gICAgcmV0dXJuIFsuLi5hY3RpdmVTdG9yZXMua2V5cygpXS5tYXAoa2V5ID0+IHtcbiAgICAgICAgbGV0IHNsYXNoID0ga2V5LmluZGV4T2YoXCIvXCIpO1xuICAgICAgICByZXR1cm4geyBhY2NvdW50OiBrZXkuc2xpY2UoMCwgc2xhc2gpLCBidWNrZXROYW1lOiBrZXkuc2xpY2Uoc2xhc2ggKyAxKSB9O1xuICAgIH0pO1xufVxuXG5leHBvcnQgdHlwZSBTZXJ2ZXJCdWNrZXRJbmZvID0ge1xuICAgIGJ1Y2tldE5hbWU6IHN0cmluZztcbiAgICBhY3RpdmU6IGJvb2xlYW47XG4gICAgLyoqIFdoZXJlIHRoZSBidWNrZXQncyBkYXRhIGxpdmVzIG9uIHRoaXMgc2VydmVyICovXG4gICAgZm9sZGVyOiBzdHJpbmc7XG4gICAgLyoqIFRoZSBkcml2ZSB0aGF0IGZvbGRlciBpcyBvbi4gQnVja2V0cyBzaGFyaW5nIGEgZHJpdmUgcmVwb3J0IHRoZSBzYW1lIG51bWJlcnMuICovXG4gICAgZGlzaz86IEJ1Y2tldERpc2tJbmZvO1xuICAgIGRpc2tFcnJvcj86IHN0cmluZztcbiAgICB3cml0ZVN0YXRzPzogQnVja2V0V3JpdGVTdGF0cztcbiAgICBjb25maWc/OiBBcmNoaXZlc0NvbmZpZztcbiAgICBlcnJvcj86IHN0cmluZztcbn07XG5cbmV4cG9ydCB0eXBlIEFjdGl2ZUJ1Y2tldEluZm8gPSB7XG4gICAgZm9sZGVyOiBzdHJpbmc7XG4gICAgLyoqIFRoZSBidWNrZXQncyByb3V0aW5nIGNvbmZpZywgdGhlIG5ld2VzdCBjb3B5IGFtb25nIGl0cyBzdG9yZXMuIEFic2VudCB3aGVuIG5vbmUgb2YgdGhlbSBoYXMgb25lIHlldC4gKi9cbiAgICByb3V0aW5nPzogUmVtb3RlQ29uZmlnO1xuICAgIGNvbmZpZzogQXJjaGl2ZXNDb25maWc7XG59O1xuXG4vKiogVGhlIHN0YXRlIG9mIE9ORSBhY3RpdmUgYnVja2V0LiBSZXR1cm5zIGFuIGVycm9yIHN0cmluZyB3aGVuIHRoZSBidWNrZXQgaXMgbm90IGFjdGl2ZSBoZXJlLCB3aGljaCBpcyB0aGUgbm9ybWFsIHN0YXRlIGZvciBhIGJ1Y2tldCBub3RoaW5nIGhhcyBhY2Nlc3NlZCBzaW5jZSBzdGFydHVwLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlYnVnR2V0QWN0aXZlQnVja2V0KGFjY291bnQ6IHN0cmluZywgYnVja2V0TmFtZTogc3RyaW5nKTogUHJvbWlzZTxBY3RpdmVCdWNrZXRJbmZvIHwgc3RyaW5nPiB7XG4gICAgbGV0IGtleSA9IGAke2FjY291bnR9LyR7YnVja2V0TmFtZX1gO1xuICAgIGxldCBvcGVuZWQgPSBhY3RpdmVTdG9yZXMuZ2V0KGtleSk7XG4gICAgaWYgKCFvcGVuZWQgfHwgIW9wZW5lZC5zaXplKSB7XG4gICAgICAgIHJldHVybiBgQnVja2V0ICR7a2V5fSBpcyBub3QgYWN0aXZlIG9uIHRoaXMgc2VydmVyIChhIGJ1Y2tldCBhY3RpdmF0ZXMgb24gZmlyc3QgYWNjZXNzKWA7XG4gICAgfVxuICAgIGxldCBidWNrZXRTdG9yZXMgPSBbLi4ub3BlbmVkLnZhbHVlcygpXTtcbiAgICBsZXQgcm91dGluZyA9IGF3YWl0IHJlYWRSb3V0aW5nRnJvbURpc2soYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgcmV0dXJuIHsgZm9sZGVyOiBidWNrZXRTdG9yZXNbMF0uZm9sZGVyLCByb3V0aW5nLCBjb25maWc6IGFnZ3JlZ2F0ZUFyY2hpdmVzQ29uZmlnKGJ1Y2tldFN0b3Jlcywgcm91dGluZykgfTtcbn1cblxuLyoqIExvYWRzIGV2ZXJ5IHN0b3JlIG9mIGEgYnVja2V0IHRoYXQgZXhpc3RzIG9uIHRoaXMgc2VydmVyJ3MgZGlzayBpbnRvIG1lbW9yeSwgd2hpY2ggc3RhcnRzIHRoZWlyIHN5bmNocm9uaXphdGlvbiBhbmQgd2luZG93IHRpbWVycywgYW5kIHJldHVybnMgdGhlIGJ1Y2tldCdzIHN0YXRlLiBOb3RoaW5nIGlzIHdyaXR0ZW4gYW5kIG5vIG90aGVyIHNlcnZlciBpcyBjb250YWN0ZWQgLSB1bmxpa2UgYnVpbGRpbmcgYW4gQXJjaGl2ZXNDaGFpbiBmb3IgaXQsIHdoaWNoIHdvdWxkIHByb2JlIGV2ZXJ5IHNvdXJjZSBhbmQgY291bGQgd3JpdGUgdGhlIHJvdXRpbmcgY29uZmlnLiBBbHJlYWR5LWFjdGl2ZSBidWNrZXRzIGp1c3QgcmV0dXJuIHRoZWlyIHN0YXRlLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGFjdGl2YXRlQnVja2V0KGFjY291bnQ6IHN0cmluZywgYnVja2V0TmFtZTogc3RyaW5nKTogUHJvbWlzZTxBY3RpdmVCdWNrZXRJbmZvIHwgc3RyaW5nPiB7XG4gICAgbGV0IGtleSA9IGAke2FjY291bnR9LyR7YnVja2V0TmFtZX1gO1xuICAgIGxldCB3YXNBY3RpdmUgPSBhY3RpdmVTdG9yZXMuaGFzKGtleSk7XG4gICAgbGV0IGJ1Y2tldFN0b3JlcyA9IGF3YWl0IGdldEJ1Y2tldFN0b3JlcyhhY2NvdW50LCBidWNrZXROYW1lKTtcbiAgICBpZiAoIWJ1Y2tldFN0b3Jlcy5sZW5ndGgpIHtcbiAgICAgICAgcmV0dXJuIGBCdWNrZXQgJHtrZXl9IGRvZXMgbm90IGV4aXN0IG9uIHRoaXMgc2VydmVyIChpdCBoYXMgbm8gc3RvcmUgZm9sZGVycyB1bmRlciAke2dldEJ1Y2tldEZvbGRlcihcIjxuYW1lPlwiLCBhY2NvdW50LCBidWNrZXROYW1lKX0pYDtcbiAgICB9XG4gICAgLy8gV2FpdCBmb3IgdGhlIGluZGV4ZXMgdG8gbG9hZCwgc28gdGhlIHRvdGFscyB3ZSByZXR1cm4gYXJlIHRoZSByZWFsIG9uZXMgcmF0aGVyIHRoYW4gemVyb2VzIGZyb20gc3RvcmVzIHRoYXQgaGF2ZSBub3QgcmVhZCB0aGVpciBpbmRleCB5ZXQuIFRoZSBzb3VyY2Ugc2NhbnMga2VlcCBydW5uaW5nIGluIHRoZSBiYWNrZ3JvdW5kLlxuICAgIGZvciAobGV0IHMgb2YgYnVja2V0U3RvcmVzKSB7XG4gICAgICAgIGF3YWl0IHMuc3RvcmUuaW5pdCgpO1xuICAgIH1cbiAgICBpZiAoIXdhc0FjdGl2ZSkge1xuICAgICAgICBjb25zb2xlLmxvZyhgQWN0aXZhdGVkIGJ1Y2tldCAke2tleX0gb24gcmVxdWVzdDogaXRzICR7YnVja2V0U3RvcmVzLmxlbmd0aH0gc3RvcmUocykgYXJlIG5vdyBsb2FkZWQgYW5kIHN5bmNocm9uaXppbmdgKTtcbiAgICB9XG4gICAgbGV0IHJvdXRpbmcgPSBhd2FpdCByZWFkUm91dGluZ0Zyb21EaXNrKGFjY291bnQsIGJ1Y2tldE5hbWUpO1xuICAgIHJldHVybiB7IGZvbGRlcjogYnVja2V0U3RvcmVzWzBdLnN0b3JlLmZvbGRlciwgcm91dGluZywgY29uZmlnOiBhZ2dyZWdhdGVBcmNoaXZlc0NvbmZpZyhidWNrZXRTdG9yZXMubWFwKHggPT4geC5zdG9yZSksIHJvdXRpbmcpIH07XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkZWJ1Z0xpc3RBY2NvdW50QnVja2V0cyhhY2NvdW50OiBzdHJpbmcpOiBQcm9taXNlPFNlcnZlckJ1Y2tldEluZm9bXT4ge1xuICAgIGxldCBzdGFydCA9IERhdGUubm93KCk7XG4gICAgLy8gVGhlIGRpc2sgaXMgdGhlIHJlY29yZDogYSBidWNrZXQgZXhpc3RzIGhlcmUgd2hlbiBpdCBoYXMgYXQgbGVhc3Qgb25lIHN0b3JlIGZvbGRlciwgYW5kIHNldmVyYWwgbmFtZXMgZm9yIG9uZSBidWNrZXQgYXJlIHN0aWxsIG9uZSBidWNrZXRcbiAgICBsZXQgZm9sZGVycyA9IGF3YWl0IGxpc3RBY2NvdW50U3RvcmVGb2xkZXJzKGFjY291bnQpO1xuICAgIGxldCBieUJ1Y2tldCA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCk7XG4gICAgZm9yIChsZXQgc3RvcmUgb2YgZm9sZGVycykge1xuICAgICAgICBpZiAoYnlCdWNrZXQuaGFzKHN0b3JlLmJ1Y2tldE5hbWUpKSBjb250aW51ZTtcbiAgICAgICAgYnlCdWNrZXQuc2V0KHN0b3JlLmJ1Y2tldE5hbWUsIHN0b3JlLmZvbGRlcik7XG4gICAgfVxuICAgIGxldCBuYW1lcyA9IFsuLi5ieUJ1Y2tldC5rZXlzKCldO1xuICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBhd2FpdCBQcm9taXNlLmFsbChuYW1lcy5tYXAoYXN5bmMgYnVja2V0TmFtZSA9PiB7XG4gICAgICAgICAgICBsZXQga2V5ID0gYCR7YWNjb3VudH0vJHtidWNrZXROYW1lfWA7XG4gICAgICAgICAgICBsZXQgZm9sZGVyID0gYnlCdWNrZXQuZ2V0KGJ1Y2tldE5hbWUpIHx8IFwiXCI7XG4gICAgICAgICAgICBsZXQgYmFzZTogU2VydmVyQnVja2V0SW5mbyA9IHsgYnVja2V0TmFtZSwgYWN0aXZlOiBhY3RpdmVTdG9yZXMuaGFzKGtleSksIGZvbGRlciB9O1xuICAgICAgICAgICAgYmFzZS5kaXNrID0gYXdhaXQgZ2V0RGlza0luZm8oZm9sZGVyKS5jYXRjaCgoZTogRXJyb3IpID0+IHtcbiAgICAgICAgICAgICAgICBiYXNlLmRpc2tFcnJvciA9IFN0cmluZyhlLnN0YWNrID8/IGUpLnNsaWNlKDAsIDUwMCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgYmFzZS53cml0ZVN0YXRzID0gZ2V0QnVja2V0V3JpdGVTdGF0cyhrZXkpO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBsZXQgcm91dGluZyA9IGF3YWl0IHJlYWRSb3V0aW5nRnJvbURpc2soYWNjb3VudCwgYnVja2V0TmFtZSk7XG4gICAgICAgICAgICAgICAgaWYgKGJhc2UuYWN0aXZlKSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBvcGVuZWQgPSBbLi4uKGFjdGl2ZVN0b3Jlcy5nZXQoa2V5KT8udmFsdWVzKCkgfHwgW10pXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsgLi4uYmFzZSwgY29uZmlnOiBhZ2dyZWdhdGVBcmNoaXZlc0NvbmZpZyhvcGVuZWQsIHJvdXRpbmcpIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghcm91dGluZykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4geyAuLi5iYXNlLCBlcnJvcjogYE5vIHJvdXRpbmcgZmlsZSAoJHtST1VUSU5HX0ZJTEV9KSBpbiBhbnkgb2YgaXRzIHN0b3Jlc2AgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgLi4uYmFzZSwgY29uZmlnOiB7IHJlbW90ZUNvbmZpZzogcm91dGluZyB9IH07XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgLi4uYmFzZSwgZXJyb3I6IFN0cmluZygoZSBhcyBFcnJvcikuc3RhY2sgPz8gZSkuc2xpY2UoMCwgNTAwKSB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9KSk7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgICAgY29uc29sZS5sb2coYGRlYnVnTGlzdEFjY291bnRCdWNrZXRzKCR7YWNjb3VudH0pIHRvb2sgJHtEYXRlLm5vdygpIC0gc3RhcnR9bXMgZm9yICR7bmFtZXMubGVuZ3RofSBidWNrZXRzYCk7XG4gICAgfVxufVxuIl19
261
+ /* _JS_SOURCE_HASH = "936e396123327b0032ec8d8f63634734905ba795799fcfc00e19984fb096d01c"; */