sliftutils 1.7.85 → 1.7.86

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -2215,7 +2215,7 @@ declare module "sliftutils/storage/IArchives" {
2215
2215
  source: IArchives;
2216
2216
  /** The persistent identity of the endpoint: its routing URL (hosted/backblaze), or the disk folder path for the base disk source. The store persists this (via its append-only sources list) as IndexEntry.sourcesListIndex, so it must mean the same endpoint forever. */
2217
2217
  url: string;
2218
- validWindow: [number, number];
2218
+ validWindows: [number, number][];
2219
2219
  route?: [number, number];
2220
2220
  noFullSync?: boolean;
2221
2221
  intermediate?: boolean;
@@ -2227,6 +2227,7 @@ declare module "sliftutils/storage/IArchives" {
2227
2227
  export declare const FULL_ROUTE: [number, number];
2228
2228
  export declare const VARIABLE_SHARD = "VARIABLE_SHARD_f0234jfah08fgyhfgyssdds83nmp";
2229
2229
  export declare function windowAcceptsWrites(validWindow: [number, number] | undefined): boolean;
2230
+ export declare function windowsAcceptWrites(validWindows: [number, number][]): boolean;
2230
2231
  export declare const LARGE_SET_THRESHOLD: number;
2231
2232
  /** A getNextData stream over an in-memory buffer, in LARGE_SET_THRESHOLD slices - how set transparently becomes setLargeFile for large buffers. */
2232
2233
  export declare function bufferChunkStream(data: Buffer): () => Promise<Buffer | undefined>;
@@ -2247,7 +2248,7 @@ declare module "sliftutils/storage/IArchives" {
2247
2248
  } | undefined>;
2248
2249
  export type ArchivesSyncSourceStatus = {
2249
2250
  debugName: string;
2250
- validWindow: [number, number];
2251
+ validWindows: [number, number][];
2251
2252
  route?: [number, number];
2252
2253
  noFullSync?: boolean;
2253
2254
  supportsChangesAfter: boolean;
@@ -3178,7 +3179,7 @@ declare module "sliftutils/storage/remoteStorage/blobStore" {
3178
3179
  export type BlobSourceSpec = {
3179
3180
  identity: string;
3180
3181
  url: string;
3181
- validWindow: [number, number];
3182
+ validWindows: [number, number][];
3182
3183
  route?: [number, number];
3183
3184
  noFullSync?: boolean;
3184
3185
  intermediate?: boolean;
@@ -3333,6 +3334,7 @@ declare module "sliftutils/storage/remoteStorage/blobStore" {
3333
3334
  private setInternal;
3334
3335
  private cacheRead;
3335
3336
  private setOrDelete;
3337
+ private baseWriteWindowEnd;
3336
3338
  private getWritableSources;
3337
3339
  private writeToSources;
3338
3340
  private getDiskSource;
@@ -3971,7 +3973,7 @@ declare module "sliftutils/storage/remoteStorage/storageServerState" {
3971
3973
  };
3972
3974
  /** 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. */
3973
3975
  export declare function requireBucket(account: string, bucketName: string): Promise<BucketState>;
3974
- /** The store serving a request: the exact config entry the CLIENT selected, matched by equality (key order ignored) against the bucket's own entries. A match is honored even when its window has passed - the selection never validates, the store's own validation throws instead. Throws when nothing matches, listing what is available. */
3976
+ /** The store serving a request: the config entry the CLIENT selected, matched against the bucket's own entries by identity EXCLUDING the valid window (see sourceMatchKey). The selection never validates - the store's own window/route checks throw if the caller is stale - so honoring a window mismatch here is exactly right. Throws when nothing matches, listing what is available. */
3975
3977
  export declare function findBucketStore(account: string, bucketName: string, sourceConfig: SourceConfig | undefined): Promise<LoadedStore>;
3976
3978
  /** 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. */
3977
3979
  export declare function readBucketInternal(account: string, bucketName: string, config: {
@@ -4072,7 +4074,7 @@ declare module "sliftutils/storage/remoteStorage/storePlan" {
4072
4074
  };
4073
4075
  export type StoreSourceSpec = {
4074
4076
  sourceConfig?: SourceConfig;
4075
- validWindow: [number, number];
4077
+ validWindows: [number, number][];
4076
4078
  route?: [number, number];
4077
4079
  noFullSync?: boolean;
4078
4080
  };
@@ -0,0 +1,31 @@
1
+ "use strict"; var console = (function shimConsole() { let baseConsole = globalThis.console; if (typeof window !== "undefined") return baseConsole; let name = __filename.replaceAll("\\", "/").split("/").pop(); let dirName = __dirname.replaceAll("\\", "/").split("/").pop(); let context = { __FILE__: __filename, __DIR__: __dirname, __NAME__: name, __DIRNAME__: dirName }; let newConsole = { ...baseConsole }; for (let shim of ["log", "info", "warn", "error"]) { newConsole[shim] = (...args) => { args.push(context); baseConsole[shim](...args); }; } newConsole.__context = context; return newConsole; })(); "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
3
+ //exports.deepFreezeObject = exports.freezeObject = exports.isDefined = void 0;
4
+ function isDefined(value) {
5
+ return value !== undefined && value !== null;
6
+ }
7
+ exports.isDefined = isDefined;
8
+ function freezeObject(value) {
9
+ if (!value)
10
+ return value;
11
+ Object.freeze(value);
12
+ }
13
+ exports.freezeObject = freezeObject;
14
+ function deepFreezeObject(value) {
15
+ if (!value)
16
+ return;
17
+ if (typeof value !== "object")
18
+ return;
19
+ if (Object.isFrozen(value))
20
+ return;
21
+ Object.freeze(value);
22
+ Object.getOwnPropertyNames(value).forEach(prop => {
23
+ const propValue = value[prop];
24
+ if (propValue && typeof propValue === "object") {
25
+ deepFreezeObject(propValue);
26
+ }
27
+ });
28
+ }
29
+ exports.deepFreezeObject = deepFreezeObject;
30
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ0eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxTQUFnQixTQUFTLENBQUksS0FBMkI7SUFDcEQsT0FBTyxLQUFLLEtBQUssU0FBUyxJQUFJLEtBQUssS0FBSyxJQUFJLENBQUM7QUFDakQsQ0FBQztBQUZELDhCQUVDO0FBR0QsU0FBZ0IsWUFBWSxDQUFDLEtBQWM7SUFDdkMsSUFBSSxDQUFDLEtBQUs7UUFBRSxPQUFPLEtBQUssQ0FBQztJQUN6QixNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3pCLENBQUM7QUFIRCxvQ0FHQztBQUVELFNBQWdCLGdCQUFnQixDQUFDLEtBQWM7SUFDM0MsSUFBSSxDQUFDLEtBQUs7UUFBRSxPQUFPO0lBQ25CLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUTtRQUFFLE9BQU87SUFDdEMsSUFBSSxNQUFNLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQztRQUFFLE9BQU87SUFFbkMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUVyQixNQUFNLENBQUMsbUJBQW1CLENBQUMsS0FBSyxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFO1FBQzdDLE1BQU0sU0FBUyxHQUFJLEtBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN2QyxJQUFJLFNBQVMsSUFBSSxPQUFPLFNBQVMsS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUM3QyxnQkFBZ0IsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNoQyxDQUFDO0lBQ0wsQ0FBQyxDQUFDLENBQUM7QUFDUCxDQUFDO0FBYkQsNENBYUMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgZnVuY3Rpb24gaXNEZWZpbmVkPFQ+KHZhbHVlOiBUIHwgdW5kZWZpbmVkIHwgbnVsbCk6IHZhbHVlIGlzIFQge1xuICAgIHJldHVybiB2YWx1ZSAhPT0gdW5kZWZpbmVkICYmIHZhbHVlICE9PSBudWxsO1xufVxuXG5cbmV4cG9ydCBmdW5jdGlvbiBmcmVlemVPYmplY3QodmFsdWU6IHVua25vd24pIHtcbiAgICBpZiAoIXZhbHVlKSByZXR1cm4gdmFsdWU7XG4gICAgT2JqZWN0LmZyZWV6ZSh2YWx1ZSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZWVwRnJlZXplT2JqZWN0KHZhbHVlOiB1bmtub3duKSB7XG4gICAgaWYgKCF2YWx1ZSkgcmV0dXJuO1xuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09IFwib2JqZWN0XCIpIHJldHVybjtcbiAgICBpZiAoT2JqZWN0LmlzRnJvemVuKHZhbHVlKSkgcmV0dXJuO1xuXG4gICAgT2JqZWN0LmZyZWV6ZSh2YWx1ZSk7XG5cbiAgICBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh2YWx1ZSkuZm9yRWFjaChwcm9wID0+IHtcbiAgICAgICAgY29uc3QgcHJvcFZhbHVlID0gKHZhbHVlIGFzIGFueSlbcHJvcF07XG4gICAgICAgIGlmIChwcm9wVmFsdWUgJiYgdHlwZW9mIHByb3BWYWx1ZSA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgZGVlcEZyZWV6ZU9iamVjdChwcm9wVmFsdWUpO1xuICAgICAgICB9XG4gICAgfSk7XG59Il19
31
+ /* _JS_SOURCE_HASH = "31d7d1a02df8f0a0fc8bfd8d981e6b75244189b8af32fbe94f4cb1c60ed932d0"; */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sliftutils",
3
- "version": "1.7.85",
3
+ "version": "1.7.86",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "files": [
@@ -133,7 +133,7 @@ export type ArchivesSource = {
133
133
  source: IArchives;
134
134
  /** The persistent identity of the endpoint: its routing URL (hosted/backblaze), or the disk folder path for the base disk source. The store persists this (via its append-only sources list) as IndexEntry.sourcesListIndex, so it must mean the same endpoint forever. */
135
135
  url: string;
136
- validWindow: [number, number];
136
+ validWindows: [number, number][];
137
137
  route?: [number, number];
138
138
  noFullSync?: boolean;
139
139
  intermediate?: boolean;
@@ -145,6 +145,7 @@ export declare const STORAGE_WRONG_ROUTE = "REMOTE_STORAGE_WRONG_ROUTE_c94d2e17"
145
145
  export declare const FULL_ROUTE: [number, number];
146
146
  export declare const VARIABLE_SHARD = "VARIABLE_SHARD_f0234jfah08fgyhfgyssdds83nmp";
147
147
  export declare function windowAcceptsWrites(validWindow: [number, number] | undefined): boolean;
148
+ export declare function windowsAcceptWrites(validWindows: [number, number][]): boolean;
148
149
  export declare const LARGE_SET_THRESHOLD: number;
149
150
  /** A getNextData stream over an in-memory buffer, in LARGE_SET_THRESHOLD slices - how set transparently becomes setLargeFile for large buffers. */
150
151
  export declare function bufferChunkStream(data: Buffer): () => Promise<Buffer | undefined>;
@@ -165,7 +166,7 @@ export declare function copyArchiveFile(config: {
165
166
  } | undefined>;
166
167
  export type ArchivesSyncSourceStatus = {
167
168
  debugName: string;
168
- validWindow: [number, number];
169
+ validWindows: [number, number][];
169
170
  route?: [number, number];
170
171
  noFullSync?: boolean;
171
172
  supportsChangesAfter: boolean;
@@ -177,8 +177,8 @@ export type ArchivesSource = {
177
177
  source: IArchives;
178
178
  /** The persistent identity of the endpoint: its routing URL (hosted/backblaze), or the disk folder path for the base disk source. The store persists this (via its append-only sources list) as IndexEntry.sourcesListIndex, so it must mean the same endpoint forever. */
179
179
  url: string;
180
- // From the source's CommonConfig. The window routes WRITES: once its end is past (see windowAcceptsWrites) the source stops receiving writes entirely - it just stops growing. It does NOT filter scanning: a scan is us asking the source what it already holds, and existing values synchronize regardless of their write times (the same reasoning that lets synchronization ignore the immutable flag).
181
- validWindow: [number, number];
180
+ // From the source's CommonConfig, but ALL of them: the same endpoint (same url+route, ignoring the window) can appear in the routing config under several windows at once - most commonly when a deploy switchover has split one window in two around an intermediate. It is ONE source that knows all its windows, never several sources. The window routes WRITES: the source receives writes while ANY of its windows is still open (see windowsAcceptWrites). Windows do NOT filter scanning: a scan is us asking the source what it already holds, and existing values synchronize regardless of their write times (the same reasoning that lets synchronization ignore the immutable flag).
181
+ validWindows: [number, number][];
182
182
  // From the source's CommonConfig (intersected with the owning store's own route): only keys routing into [start, end) are accepted from this source's scans and sent to it in writes/reconciliation. The routing file is exempt - config flows everywhere. Absent = all keys.
183
183
  route?: [number, number];
184
184
  // From the source's CommonConfig; see there.
@@ -207,6 +207,10 @@ export function windowAcceptsWrites(validWindow: [number, number] | undefined):
207
207
  if (!validWindow) return true;
208
208
  return validWindow[1] > Date.now();
209
209
  }
210
+ // A source (which can hold several windows) accepts writes while ANY of its windows is still open. No windows = the base disk of an inert store (not in the config), which never receives fan-out writes anyway.
211
+ export function windowsAcceptWrites(validWindows: [number, number][]): boolean {
212
+ return validWindows.some(windowAcceptsWrites);
213
+ }
210
214
 
211
215
  const LARGE_COPY_THRESHOLD = 64 * 1024 * 1024;
212
216
  const LARGE_COPY_CHUNK = 32 * 1024 * 1024;
@@ -276,7 +280,7 @@ export async function copyArchiveFile(config: {
276
280
 
277
281
  export type ArchivesSyncSourceStatus = {
278
282
  debugName: string;
279
- validWindow: [number, number];
283
+ validWindows: [number, number][];
280
284
  route?: [number, number];
281
285
  noFullSync?: boolean;
282
286
  supportsChangesAfter: boolean;
@@ -1,7 +1,7 @@
1
1
  "use strict"; var console = (function shimConsole() { let baseConsole = globalThis.console; if (typeof window !== "undefined") return baseConsole; let name = __filename.replaceAll("\\", "/").split("/").pop(); let dirName = __dirname.replaceAll("\\", "/").split("/").pop(); let context = { __FILE__: __filename, __DIR__: __dirname, __NAME__: name, __DIRNAME__: dirName }; let newConsole = { ...baseConsole }; for (let shim of ["log", "info", "warn", "error"]) { newConsole[shim] = (...args) => { args.push(context); baseConsole[shim](...args); }; } newConsole.__context = context; return newConsole; })(); "use strict";
2
2
  // The important operations of an archive bucket (extracted from ArchivesBackblaze), so other backends (e.g. our own remote storage server) can be used interchangeably.
3
3
  Object.defineProperty(exports, "__esModule", { value: true , configurable: true});
4
- //exports.copyArchiveFile = exports.bufferChunkStream = exports.LARGE_SET_THRESHOLD = exports.windowAcceptsWrites = exports.VARIABLE_SHARD = exports.FULL_ROUTE = exports.STORAGE_WRONG_ROUTE = exports.STORAGE_WRONG_VALID_WINDOW = exports.FULL_VALID_WINDOW = exports.assertValidLastModified = exports.IMMUTABLE_CACHE_TIME = exports.MAX_LAST_MODIFIED_FUTURE = void 0;
4
+ //exports.copyArchiveFile = exports.bufferChunkStream = exports.LARGE_SET_THRESHOLD = exports.windowsAcceptWrites = exports.windowAcceptsWrites = exports.VARIABLE_SHARD = exports.FULL_ROUTE = exports.STORAGE_WRONG_ROUTE = exports.STORAGE_WRONG_VALID_WINDOW = exports.FULL_VALID_WINDOW = exports.assertValidLastModified = exports.IMMUTABLE_CACHE_TIME = exports.MAX_LAST_MODIFIED_FUTURE = void 0;
5
5
  // A write may not be stamped more than this far in the future, or clock skew between machines would let a bad timestamp block writes for a long time.
6
6
  exports.MAX_LAST_MODIFIED_FUTURE = 15 * 60 * 1000;
7
7
  // How long browsers may cache files from immutable buckets (the Cache-Control max-age), shared by every hosting path (backblaze bucket settings and our own storage server's HTTP route)
@@ -29,6 +29,11 @@ function windowAcceptsWrites(validWindow) {
29
29
  return validWindow[1] > Date.now();
30
30
  }
31
31
  exports.windowAcceptsWrites = windowAcceptsWrites;
32
+ // A source (which can hold several windows) accepts writes while ANY of its windows is still open. No windows = the base disk of an inert store (not in the config), which never receives fan-out writes anyway.
33
+ function windowsAcceptWrites(validWindows) {
34
+ return validWindows.some(windowAcceptsWrites);
35
+ }
36
+ exports.windowsAcceptWrites = windowsAcceptWrites;
32
37
  const LARGE_COPY_THRESHOLD = 64 * 1024 * 1024;
33
38
  const LARGE_COPY_CHUNK = 32 * 1024 * 1024;
34
39
  // Above this, set transparently streams through setLargeFile: one giant wire message would exceed the transport limit and lag every other client sharing the connection
@@ -87,5 +92,5 @@ async function copyArchiveFile(config) {
87
92
  return { writeTime: finalWriteTime, size: totalSize };
88
93
  }
89
94
  exports.copyArchiveFile = copyArchiveFile;
90
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiSUFyY2hpdmVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiSUFyY2hpdmVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSx3S0FBd0s7OztBQUV4SyxzSkFBc0o7QUFDekksUUFBQSx3QkFBd0IsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQUV2RCx5TEFBeUw7QUFDNUssUUFBQSxvQkFBb0IsR0FBRyxLQUFLLEdBQUcsSUFBSSxDQUFDO0FBQ2pELFNBQWdCLHVCQUF1QixDQUFDLFlBQW9CO0lBQ3hELElBQUksR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxnQ0FBd0IsQ0FBQztJQUNoRCxJQUFJLFlBQVksR0FBRyxHQUFHLEVBQUUsQ0FBQztRQUNyQixNQUFNLElBQUksS0FBSyxDQUFDLDBDQUEwQyxZQUFZLE1BQU0sR0FBRyxxQkFBcUIsQ0FBQyxDQUFDO0lBQzFHLENBQUM7QUFDTCxDQUFDO0FBTEQsMERBS0M7QUEwRVksUUFBQSxpQkFBaUIsR0FBcUIsQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUM7QUEyR2hGLHdYQUF3WDtBQUMzVyxRQUFBLDBCQUEwQixHQUFHLDRDQUE0QyxDQUFDO0FBRXZGLDhMQUE4TDtBQUNqTCxRQUFBLG1CQUFtQixHQUFHLHFDQUFxQyxDQUFDO0FBRTVELFFBQUEsVUFBVSxHQUFxQixDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUVuRCwyUkFBMlI7QUFDOVEsUUFBQSxjQUFjLEdBQUcsNkNBQTZDLENBQUM7QUFDNUUsb0xBQW9MO0FBQ3BMLDhKQUE4SjtBQUM5SixTQUFnQixtQkFBbUIsQ0FBQyxXQUF5QztJQUN6RSxJQUFJLENBQUMsV0FBVztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQzlCLE9BQU8sV0FBVyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztBQUN2QyxDQUFDO0FBSEQsa0RBR0M7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SSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEdBQUcsZ0JBQWdCLEVBQUUsU0FBUyxDQUFDLENBQUM7WUFDekQsSUFBSSxJQUFJLEdBQUcsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxFQUFFLEtBQUssRUFBRSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLEVBQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQyxRQUFRLEVBQUUsV0FBVyxFQUFFLE1BQU0sQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO1lBQy9ILElBQUksQ0FBQyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQ3hCLE1BQU0sSUFBSSxLQUFLLENBQUMsa0JBQWtCLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFNBQVMsSUFBSSxDQUFDLFlBQVksRUFBRSxhQUFhLElBQUksSUFBSSxJQUFJLENBQUMsTUFBTSxJQUFJLFNBQVMsT0FBTyxNQUFNLElBQUksR0FBRyxjQUFjLEdBQUcsR0FBRyxNQUFNLGVBQWUsU0FBUywrQ0FBK0MsQ0FBQyxDQUFDO1lBQzFQLENBQUM7WUFDRCxNQUFNLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQztZQUN0QixPQUFPLElBQUksQ0FBQztRQUNoQixDQUFDO0tBQ0osQ0FBQyxDQUFDO0lBQ0gsT0FBTyxFQUFFLFNBQVMsRUFBRSxjQUFjLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxDQUFDO0FBQzFELENBQUM7QUE5Q0QsMENBOENDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gVGhlIGltcG9ydGFudCBvcGVyYXRpb25zIG9mIGFuIGFyY2hpdmUgYnVja2V0IChleHRyYWN0ZWQgZnJvbSBBcmNoaXZlc0JhY2tibGF6ZSksIHNvIG90aGVyIGJhY2tlbmRzIChlLmcuIG91ciBvd24gcmVtb3RlIHN0b3JhZ2Ugc2VydmVyKSBjYW4gYmUgdXNlZCBpbnRlcmNoYW5nZWFibHkuXG5cbi8vIEEgd3JpdGUgbWF5IG5vdCBiZSBzdGFtcGVkIG1vcmUgdGhhbiB0aGlzIGZhciBpbiB0aGUgZnV0dXJlLCBvciBjbG9jayBza2V3IGJldHdlZW4gbWFjaGluZXMgd291bGQgbGV0IGEgYmFkIHRpbWVzdGFtcCBibG9jayB3cml0ZXMgZm9yIGEgbG9uZyB0aW1lLlxuZXhwb3J0IGNvbnN0IE1BWF9MQVNUX01PRElGSUVEX0ZVVFVSRSA9IDE1ICogNjAgKiAxMDAwO1xuXG4vLyBIb3cgbG9uZyBicm93c2VycyBtYXkgY2FjaGUgZmlsZXMgZnJvbSBpbW11dGFibGUgYnVja2V0cyAodGhlIENhY2hlLUNvbnRyb2wgbWF4LWFnZSksIHNoYXJlZCBieSBldmVyeSBob3N0aW5nIHBhdGggKGJhY2tibGF6ZSBidWNrZXQgc2V0dGluZ3MgYW5kIG91ciBvd24gc3RvcmFnZSBzZXJ2ZXIncyBIVFRQIHJvdXRlKVxuZXhwb3J0IGNvbnN0IElNTVVUQUJMRV9DQUNIRV9USU1FID0gODY0MDAgKiAxMDAwO1xuZXhwb3J0IGZ1bmN0aW9uIGFzc2VydFZhbGlkTGFzdE1vZGlmaWVkKGxhc3RNb2RpZmllZDogbnVtYmVyKTogdm9pZCB7XG4gICAgbGV0IG1heCA9IERhdGUubm93KCkgKyBNQVhfTEFTVF9NT0RJRklFRF9GVVRVUkU7XG4gICAgaWYgKGxhc3RNb2RpZmllZCA+IG1heCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGxhc3RNb2RpZmllZCBpcyB0b28gZmFyIGluIHRoZSBmdXR1cmU6ICR7bGFzdE1vZGlmaWVkfSA+ICR7bWF4fSAobm93ICsgMTUgbWludXRlcylgKTtcbiAgICB9XG59XG5cblxuZXhwb3J0IHR5cGUgUmVtb3RlQ29uZmlnID0ge1xuICAgIC8vIE5PVEU6IFZlcnNpb24gaXMgdXNlZCB3aGVuIHVwZGF0aW5nIHRoZSBjb25maWd1cmF0aW9uLiBUaGUgbmV3ZXIgdmVyc2lvbiBpcyBhbHdheXMgdGFrZW4uIEEgbWlzc2luZyB2ZXJzaW9uIGNvdW50cyBhcyB2ZXJzaW9uIC0xLlxuICAgIHZlcnNpb24/OiBudW1iZXI7XG4gICAgc291cmNlczogUmVtb3RlQ29uZmlnQmFzZVtdO1xufTtcblxuLyoqXG4gICAgc3RyaW5nIGFyZ3VtZW50cyB3aWxsIGJlIGEgdXJsLCBsb29raW5nIGxpa2U6XG4gICAgICAgIGh0dHBzOi8vc3RvcmFnZTIudmlkZ3JpZHdlYi5jb206NDQ0NS9maWxlL2V4YW1wbGVhY2NvdW50L2V4YW1wbGVidWNrZXQvc3RvcmFnZS9zdG9yYWdlcm91dGluZy5qc29uXG4gICAgICAgIGh0dHBzOi8vZjAwMi5iYWNrYmxhemViMi5jb20vZmlsZS9xdWVyeXN1YnRlc3QtY29tLXB1YmxpYy1pbW11dGFibGUvc3RvcmFnZS9zdG9yYWdlcm91dGluZy5qc29uXG4gICAgICAgIC0gVGhlc2UgbWFwIHRvIHsgdXJsIH0sIHdpdGggdGhlIHR5cGUgaW5mZXJyZWQgZnJvbSB0aGUgdXJsXG4gICAgICAgIC0gSG9zdGVkIHVybHMgYXJlIC9maWxlLzxhY2NvdW50Pi88YnVja2V0TmFtZT4vLi4uLCBiYWNrYmxhemUgdXJscyBhcmUgL2ZpbGUvPGJ1Y2tldE5hbWU+Ly4uLlxuXG4gICAgTk9URTogSWYgd2UgZG8gbm90IGhhdmUgcmlnaHQgYWNjZXNzIHRvIHRoZXNlLCB0aGVuIGl0IGJlY29tZXMgYSByZWFkLW9ubHkgSUFyY2hpdmVzLCB3aGVyZSB3ZSBzb2xlbHkgcmVhZCB1c2luZyB0aGUgdXJsIGZvcm0gKHdoaWNoIG1pZ2h0IHRocm93IGR1ZSB0byBub3QgaGF2aW5nIGFjY2VzcyBhcyB3ZWxsKS4gVU5MRVNTIE91ciBjb25maWd1cmF0aW9uIGV4cGxpY2l0bHkgaGFzIHB1YmxpYzogZmFsc2UsIGluIHdoaWNoIGNhc2UsIHdlIGRvbid0IGV2ZW4gaGl0IHRoZSBVUkwgYW5kIHdlIHRocm93IG9uIGFjY2Vzcy5cblxuICAgIE5PVEU6IElmIHdlJ3JlIGluIHRoZSBicm93c2VyLCB3ZSBzaG91bGQgYWxsb3cgZG93bmxvYWRpbmcgdGhlIGZpbGVzIHZpYSB0aGUgVVJMIGZvcm0gKGlmIGl0J3MgYSBwdWJsaWMgYnVja2V0KSwgaG93ZXZlciwgd2Ugd29uJ3QgYWxsb3cgd3JpdGluZywgYmVjYXVzZSB0aGVpciBzZXJ2ZXJzIGRvIG5vdCBhbGxvdyBzZWN1cmUgYnJvd3NlciB3cml0ZXMuXG4qL1xuZXhwb3J0IHR5cGUgUmVtb3RlQ29uZmlnQmFzZSA9IHN0cmluZyB8IFNvdXJjZUNvbmZpZztcblxuLyoqIE9uZSBjb25maWd1cmVkIHNvdXJjZSBpbiBhIHJvdXRpbmcgY29uZmlnOiBhIGhvc3RlZCAob3VyIHN0b3JhZ2Ugc2VydmVyKSBvciBiYWNrYmxhemUgZW50cnkuIFJlcXVlc3RzIGNhcnJ5IHRoZSBleGFjdCBTb3VyY2VDb25maWcgdGhleSBzZWxlY3RlZCwgYW5kIHRoZSBzZXJ2ZXIgbWF0Y2hlcyBpdCBhZ2FpbnN0IGl0cyBvd24gZW50cmllcyB0byBwaWNrIHRoZSBiYWNraW5nIHN0b3JlLiAqL1xuZXhwb3J0IHR5cGUgU291cmNlQ29uZmlnID0gSG9zdGVkQ29uZmlnIHwgQmFja2JsYXplQ29uZmlnO1xuXG5leHBvcnQgdHlwZSBDb21tb25Db25maWcgPSB7XG4gICAgLyoqIEJ5IGRlZmF1bHQgYSBzZXJ2ZXIgaG9zdGluZyB0aGlzIGJ1Y2tldCBlYWdlcmx5IGNvcGllcyB0aGlzIHNvdXJjZSdzIGZ1bGwgY29udGVudHMgb250byBpdHMgb3duIGRpc2sgKG9uIHRvcCBvZiB0aGUgbGF6eSByZWFkLXRocm91Z2ggY2FjaGluZykuIFNldCB0aGlzIHRvIGJlIGEgZnJvbnQgZW5kIGZvciBhIHZlcnkgbGFyZ2UgZGF0YWJhc2Ugd2l0aG91dCBjb3B5aW5nIHRoZSBmdWxsIGRhdGFiYXNlIC0gcmVhZHMgc3RpbGwgZG93bi1jYWNoZSBpbmRpdmlkdWFsIGZpbGVzIG9uIGRlbWFuZC4gKi9cbiAgICBub0Z1bGxTeW5jPzogYm9vbGVhbjtcbiAgICAvKiogQnl0ZXMgb2YgcmVhZC1jYWNoZSB0aGlzIHNlcnZlcidzIGRpc2sgbWF5IGhvbGQ7IGxlYXN0LXJlY2VudGx5LXVzZWQgZmlsZXMgYXJlIGRlbGV0ZWQgZnJvbSBkaXNrIHRvIHN0YXkgdW5kZXIgaXQgKG9ubHkgZXZlciB3aGVuIGFub3RoZXIgc291cmNlIHZlcmlmaWFibHkgaG9sZHMgdGhlIGZpbGUgLSB0aGUgb25seSBjb3B5IGlzIG5ldmVyIGRlbGV0ZWQpLiBSZXF1aXJlcyBub0Z1bGxTeW5jIChhIGZ1bGwgY29weSBjYW4ndCBiZSBib3VuZGVkKS4gKi9cbiAgICByZWFkZXJEaXNrTGltaXQ/OiBudW1iZXI7XG4gICAgLyoqIFRoZSB3cml0ZSB0aW1lcyAoW3N0YXJ0TXMsIGVuZE1zXSkgdGhpcyBzb3VyY2UgaXMgdmFsaWQgZm9yIChzZWUgQXJjaGl2ZXNTb3VyY2UudmFsaWRXaW5kb3cgZm9yIHRoZSBzeW5jaHJvbml6YXRpb24gc2VtYW50aWNzKS4gUmVxdWlyZWQgb24gb2JqZWN0IGNvbmZpZ3M6IGNvbmZpZ3VyYXRpb24gY2hhbmdlcyBtdXN0IGJlIFNDSEVEVUxFRCAoYSBuZXcgc291cmNlIGJlY29tZXMgdmFsaWQgYXQgYSBmdXR1cmUgdGltZSB3aGlsZSB0aGUgb2xkIG9uZSdzIHdpbmRvdyBlbmRzKSwgbm90IGZsaXBwZWQgaW5zdGFudGx5LiBQbGFpbiBVUkwtc3RyaW5nIHNvdXJjZXMgZGVmYXVsdCB0byBGVUxMX1ZBTElEX1dJTkRPVyAtIG9uY2UgeW91J3JlIHdyaXRpbmcgb2JqZWN0IGNvbmZpZ3MsIHlvdSdyZSBkb2luZyBzb21ldGhpbmcgY29tcGxpY2F0ZWQgZW5vdWdoIHRvIHRoaW5rIGFib3V0IHdoZW4gdGhpbmdzIGNoYW5nZS4gKi9cbiAgICB2YWxpZFdpbmRvdzogW251bWJlciwgbnVtYmVyXTtcbiAgICAvKiogU2hhcmRpbmc6IHRoZSBmcmFjdGlvbiBvZiB0aGUga2V5IHNwYWNlIHRoaXMgc291cmNlIGhhbmRsZXMsIGFzIFtzdGFydCwgZW5kKSBvdmVyIFswLCAxKSAoa2V5cyBhcmUgcm91dGVkIGJ5IGdldFJvdXRlIGluIHJlbW90ZUNvbmZpZy50cykuIERlZmF1bHRzIHRvIEZVTExfUk9VVEUgKHVuc2hhcmRlZCkuIEF0IGV2ZXJ5IHBvaW50IGluIHRpbWUgdGhlIHNvdXJjZXMnIHJvdXRlcyBtdXN0IGZ1bGx5IGNvdmVyIFswLCAxKSwgb3Igc29tZSBrZXlzIGNvdWxkIG5ldmVyIGJlIHJlYWQuICovXG4gICAgcm91dGU/OiBbbnVtYmVyLCBudW1iZXJdO1xuICAgIC8qKiBTZXQgb24gZW50cmllcyBpbmplY3RlZCBpbnRvIHRoZSBpbi1tZW1vcnkgY29uZmlnIGJ5IGFuIG92ZXJsYXkgKGEgZGVwbG95IHN3aXRjaG92ZXIncyBhbHRlcm5hdGUtcG9ydCB3aW5kb3cpLiBOZXZlciB3cml0dGVuIHRvIGRpc2s6IHJlc29sdmVJbnRlcm1lZGlhdGVTb3VyY2VzIHN0cmlwcyB0aGVzZSBhbmQgcmVqb2lucyB0aGUgd2luZG93cyBhcm91bmQgdGhlbSwgd2hpY2ggaXMgYWxzbyBob3cgYSBjbGllbnQgdGVsbHMgd2hldGhlciBhbiB1cGRhdGUgaXMgYSByZWFsIGNvbmZpZ3VyYXRpb24gY2hhbmdlIG9yIGp1c3QgYW4gb3ZlcmxheS4gKi9cbiAgICBpbnRlcm1lZGlhdGU/OiBib29sZWFuO1xufTtcblxuZXhwb3J0IHR5cGUgSG9zdGVkQ29uZmlnID0gQ29tbW9uQ29uZmlnICYge1xuICAgIHR5cGU6IFwicmVtb3RlXCI7XG5cbiAgICAvLyBFeDogaHR0cHM6Ly85OS0yNTAtMTI0LTkxLnF1ZXJ5c3VidGVzdC5jb206NTIzMy9maWxlL3Jvb3QvdW5pcXVlYnVja2V0bmFtZS9zdG9yYWdlL3N0b3JhZ2Vyb3V0aW5nLmpzb25cbiAgICAvLyBOT1RFOiBUaGUgYWNjb3VudCBhbmQgYnVja2V0IG5hbWUgYXJlIG9idGFpbmVkIGZyb20gdGhlIFVSTC5cbiAgICB1cmw6IHN0cmluZztcblxuICAgIC8vIE5PVEU6IEF1dGhlbnRpY2F0aW9uIGlzIGhhbmRsZWQgYnkgY2VydC50cywgdmlhIGhhdmluZyB5b3VyIG1hY2hpbmUgdHJ1c3RlZCB0byBhY2Nlc3MgdGhpcyBhY2NvdW50LiBcblxuICAgIHB1YmxpYz86IGJvb2xlYW47XG4gICAgLy8gRmFzdCBtb2RlOiB0aGUgc2VydmVyIGFja25vd2xlZGdlcyB3cml0ZXMgb25jZSB0aGV5IGFyZSBpbiBtZW1vcnksIGZsdXNoaW5nIHRvIGRpc2sgYWZ0ZXIgd3JpdGVEZWxheSAoZGVmYXVsdCA1IG1pbnV0ZXMpIGFuZCBjb2FsZXNjaW5nIHdyaXRlcyB0byB0aGUgc2FtZSBmaWxlLiBBIHNlcnZlciBjcmFzaCBsb3NlcyB3cml0ZXMgdGhhdCBoYXZlbid0IGZsdXNoZWQgeWV0LlxuICAgIGZhc3Q/OiBib29sZWFuO1xuICAgIHdyaXRlRGVsYXk/OiBudW1iZXI7XG4gICAgLy8gVGhlIGJ1Y2tldCBpcyBzZXJ2ZWQgc3RyYWlnaHQgZnJvbSB0aGUgc2VydmVyJ3MgZGlzaywgd2l0aCBubyBpbmRleCDigJQgc28gbm8gZmFzdCB3cml0ZXMsIG5vIGdldFN5bmNTdGF0dXMsIGFuZCBnZXRDaGFuZ2VzQWZ0ZXIyIGZhbGxzIGJhY2sgdG8gYSBmdWxsIGxpc3RpbmcuXG4gICAgcmF3RGlzaz86IGJvb2xlYW47XG4gICAgLy8gV3JpdGVzIHRvIHBhdGhzIHRoYXQgYWxyZWFkeSBleGlzdCBhcmUgZGlzYWxsb3dlZCAoZGVsZXRlcyBzdGlsbCB3b3JrKS5cbiAgICBpbW11dGFibGU/OiBib29sZWFuO1xufTtcblxuZXhwb3J0IHR5cGUgQmFja2JsYXplQ29uZmlnID0gQ29tbW9uQ29uZmlnICYge1xuICAgIHR5cGU6IFwiYmFja2JsYXplXCI7XG4gICAgLy8gRXg6IGh0dHBzOi8vZjAwMi5iYWNrYmxhemViMi5jb20vZmlsZS9xdWVyeXN1YnRlc3QtY29tLXB1YmxpYy1pbW11dGFibGUvc3RvcmFnZS9zdG9yYWdlcm91dGluZy5qc29uXG4gICAgLy8gTk9URTogVGhlIGJ1Y2tldCBuYW1lIGlzIG9idGFpbmVkIGZyb20gdGhlIFVSTC5cbiAgICB1cmw6IHN0cmluZztcbiAgICAvLyBQdWJsaWMgYnVja2V0cyBhcmUgc2VydmVkIG92ZXIgcGxhaW4gSFRUUFMgR0VUcyAoZ2V0VVJMKS4gUHJpdmF0ZSBidWNrZXRzIGFyZSBBUEktYWNjZXNzIG9ubHkuXG4gICAgcHVibGljPzogYm9vbGVhbjtcbiAgICAvLyBOT1RFOiBUaGlzIGlzbid0IGVuZm9yY2VkIG9uIHRoZSBiYWNrYmxhemUgbGV2ZWwsIHNvIHRoaXMgaXMganVzdCBhIGNsaWVudC1zaWRlIGd1YXJhbnRlZS4gVGhpcyBjYW4gY2hhbmdlIGhvdyB3ZSBjYWNoZSBmaWxlcy5cbiAgICAvLyAgLSBCYWNrYmxhemUgZG9lcyBzdXBwb3J0IGltbXV0YWJpbGl0eS4gSG93ZXZlciwgYXBwYXJlbnRseSwgb25jZSB3ZSBlbmFibGUgaXQgb24gYSBidWNrZXQsIHdlIGNhbid0IGRpc2FibGUgaXQsIHdoaWNoIGlzIHJlYWxseSBiYWQsIGFzIGl0IG1lYW5zIGlmIG91ciBjb2RlIGNvdWxkIGV2ZXIgZW5hYmxlIGl0IGFuZCB3ZSBhY2NpZGVudGFsbHkgZW5hYmxlIGl0IG9uIGFuIGltcG9ydGFudCBidWNrZXQsIHdlIGVzc2VudGlhbGx5IGp1c3QgYnJpY2tlZCB0aGF0IGJ1Y2tldC4gU28gd2Ugc2hvdWxkIG5ldmVyIHdyaXRlIGFueSBjb2RlIHRoYXQgZXZlciB0cmllcyB0byB1c2UgYmFja2JsYXplIHRvIG1ha2UgdGhpbmdzIGltbXV0YWJsZS4gXG4gICAgaW1tdXRhYmxlPzogYm9vbGVhbjtcbiAgICAvLyBDT1JTIG9yaWdpbnMgYWxsb3dlZCB0byBjb25zdW1lIHRoZSBidWNrZXQncyBmaWxlcyBpbiBhIGJyb3dzZXIuIE5vdCBhIHNlY3VyaXR5IGJvdW5kYXJ5IChhY2Nlc3MgaXMgZ2F0ZWQgYnkgdGhlIEFQSSBrZXkgLyBzaWduZWQgVVJMcywgbmVpdGhlciBvZiB3aGljaCByaWRlcyBpbiBjb29raWVzKSAtIGl0IG9ubHkgY29udHJvbHMgd2hpY2ggc2l0ZXMnIGluLXBhZ2UgSmF2YVNjcmlwdCBjYW4gcmVhZCByZXNwb25zZXMuIERlZmF1bHRzIHRvIGFueSBIVFRQUyBvcmlnaW4uXG4gICAgYWxsb3dlZE9yaWdpbnM/OiBzdHJpbmdbXTtcblxuICAgIC8vIE5PVEU6IFdlIHdpbGwgYWNjZXNzIHRoZSBhcGkga2V5IGZyb20gZ2V0U2VjcmV0LCBzZWUgYmFja2JsYXplLnRzIGZvciB0aGUgc3BlY2lmaWMga2V5cy5cbn07XG5cblxuZXhwb3J0IGNvbnN0IEZVTExfVkFMSURfV0lORE9XOiBbbnVtYmVyLCBudW1iZXJdID0gWzAsIE51bWJlci5NQVhfU0FGRV9JTlRFR0VSXTtcblxuXG5cblxuZXhwb3J0IHR5cGUgR2V0Q29uZmlnID0ge1xuICAgIHJhbmdlPzogeyBzdGFydDogbnVtYmVyOyBlbmQ6IG51bWJlciB9O1xuICAgIC8qKiBSZWFkIE9OTFkgZnJvbSB0aGUgcHJpbWFyeSBzb3VyY2UgLSB0aGUgb25lIHdyaXRlcyB3b3VsZCB0YXJnZXQgLSBpbnN0ZWFkIG9mIGZhbGxpbmcgYmFjayBhY3Jvc3MgdGhlIHJlZHVuZGFudCBzb3VyY2VzLiBVc2UgdGhpcyB3aGVuIHlvdSB3YW50IHlvdXIgcmVhZHMgYW5kIHdyaXRlcyB0byBiZSBzb21ld2hhdCBhdG9taWM6IHRoZXJlIHdpbGwgc3RpbGwgYmUgaXNzdWVzIHdpdGggdGhlIHJvdW5kIHRyaXAsIGJ1dCB3aXRob3V0IGl0IHlvdSBjb3VsZCB0YWxrIHRvIGEgY29tcGxldGVseSBkaWZmZXJlbnQgbm9kZSBhbmQgZ2V0IGEgbXVjaCBvbGRlciB2YWx1ZS4gTW9zdCByZWFkcyBhcmVuJ3QgZm9sbG93ZWQgYnkgYSB3cml0ZSB0aG91Z2gsIHNvIGZvciBtb3N0IGNhc2VzIGl0J3MgYmV0dGVyIHRvIGdldCBhIHZhbHVlIHRoYW4gdG8gaGF2ZSB0byB3YWl0IChvciBldmVuIHRocm93KSB3aGVuIHRoZSBwcmltYXJ5IG5vZGUgaXMgbm90IGF2YWlsYWJsZS4gKi9cbiAgICBub0ZhbGxiYWNrcz86IGJvb2xlYW47XG4gICAgLyoqIFN0b3JlLXRvLXN0b3JlIGNhbGw6IHRoZSBzZXJ2aW5nIG5vZGUgYW5zd2VycyBwdXJlbHkgZnJvbSBpdHMgb3duIGRpc2ssIGNvbXBsZXRlbHkgc2hvcnQtY2lyY3VpdGluZyBpdHMgaW5kZXggaG9sZGVycyAtIGNoYXNpbmcgaXRzIG93biByZW1vdGUgaG9sZGVycyB3aGlsZSBhbnN3ZXJpbmcgYW5vdGhlciBzdG9yZSBpcyBob3cgaW5maW5pdGUgZ2V0IGxvb3BzIGJldHdlZW4gc3RvcmVzIGZvcm0gKEEgYXNrcyBCLCBCJ3MgaW5kZXggcG9pbnRzIGJhY2sgYXQgQSwgLi4uKS4gTm8gd2luZG93IG9yIHJvdXRlIGNoZWNrcyBvbiByZWFkczogaWYgdGhlIGJ5dGVzIGFyZSBvbiBpdHMgZGlzaywgdGhlIGNhbGxlciBtYXkgaGF2ZSB0aGVtLiAqL1xuICAgIGludGVybmFsPzogYm9vbGVhbjtcbiAgICAvKiogQWxzbyByZXR1cm4gc2l6ZS0wIHJlc3VsdHMgKHRvbWJzdG9uZXMgLSBhbiBlbXB0eSBmaWxlIElTIGEgbWlzc2luZyBmaWxlKSBpbnN0ZWFkIG9mIHRyZWF0aW5nIHRoZW0gYXMgYWJzZW50LiBPZmYgYnkgZGVmYXVsdCwgbWF0Y2hpbmcgZ2V0SW5mbydzIGZsYWcgb2YgdGhlIHNhbWUgbmFtZS4gU3luY2hyb25pemF0aW9uIHBhc3NlcyB0aGlzIHNvIGEgREVMRVRFRCBmaWxlICh3aXRoIGl0cyB3cml0ZSB0aW1lKSBpcyBkaXN0aW5ndWlzaGFibGUgZnJvbSBhIGZpbGUgdGhhdCBuZXZlciBleGlzdGVkLiAqL1xuICAgIGluY2x1ZGVUb21ic3RvbmVzPzogYm9vbGVhbjtcbn07XG5cbmV4cG9ydCB0eXBlIEZpbmRDb25maWcgPSB7XG4gICAgc2hhbGxvdz86IGJvb2xlYW47XG4gICAgdHlwZT86IFwiZmlsZXNcIiB8IFwiZm9sZGVyc1wiO1xuICAgIC8qKiBMaXN0aW5ncyBub3JtYWxseSBjb21lIE9OTFkgZnJvbSB0aGUgYXV0aG9yaXRhdGl2ZSBzb3VyY2VzICh0aGUgc2FtZSBub2RlcyB3cml0ZXMgZ28gdG8gLSByZWFkLXlvdXItd3JpdGVzKS4gV2l0aCBmYWxsYmFja3MsIGEgZmFpbGluZyBzaGFyZCdzIHJvdXRlcyBhcmUgY292ZXJlZCBieSB0aGUgbmV4dCBzb3VyY2UgaG9sZGluZyB0aGVtIChlLmcuIGEgd2lkZSByZWFkIHJlcGxpY2EpIGluc3RlYWQgb2YgdGhlIGNhbGwgZmFpbGluZyAtIGhpZ2ggYXZhaWxhYmlsaXR5IGF0IHRoZSBjb3N0IG9mIHBvc3NpYmx5IG1pc3NpbmcganVzdC13cml0dGVuIGRhdGEuIFNpbmdsZS1zb3VyY2UgYXJjaGl2ZXMgaWdub3JlIHRoZSBmbGFnLiAqL1xuICAgIGZhbGxiYWNrcz86IGJvb2xlYW47XG59O1xuXG5leHBvcnQgdHlwZSBEZWxDb25maWcgPSB7XG4gICAgLyoqIFN0YW1wcyB0aGUgZGVsZXRpb24gKGl0cyB0b21ic3RvbmUpIHdpdGggdGhpcyB3cml0ZSB0aW1lIGluc3RlYWQgb2Ygbm93LiBTeW5jaHJvbml6YXRpb24gcGFzc2VzIHRoZSBPUklHSU5BTCBkZWxldGlvbiB0aW1lLCBzbyBkZWxldGlvbiBvcmRlcmluZyBzdXJ2aXZlcyBwcm9wYWdhdGlvbiBleGFjdGx5IGxpa2UgYW55IG90aGVyIHdyaXRlJ3Mgb3JkZXJpbmcuICovXG4gICAgbGFzdE1vZGlmaWVkPzogbnVtYmVyO1xuICAgIC8qKiBTZWUgU2V0Q29uZmlnLmludGVybmFsLiAqL1xuICAgIGludGVybmFsPzogYm9vbGVhbjtcbiAgICAvKiogU2VlIFNldENvbmZpZy5ub0NoZWNrcy4gKi9cbiAgICBub0NoZWNrcz86IGJvb2xlYW47XG4gICAgLyoqIFNlZSBTZXRDb25maWcuZmFsbGJhY2tzLiAqL1xuICAgIGZhbGxiYWNrcz86IGJvb2xlYW47XG59O1xuXG5leHBvcnQgdHlwZSBHZXRJbmZvQ29uZmlnID0ge1xuICAgIC8qKiBBbHNvIHJlcG9ydCBzaXplLTAgZW50cmllcyAodG9tYnN0b25lcyAtIGFuIGVtcHR5IGZpbGUgSVMgYSBtaXNzaW5nIGZpbGUpLiBPZmYgYnkgZGVmYXVsdCwgc28gYSBkZWxldGVkIGtleSByZXBvcnRzIHVuZGVmaW5lZCwgbWF0Y2hpbmcgZ2V0LiBTeW5jaHJvbml6YXRpb24tc3R5bGUgY2FsbGVycyBwYXNzIHRoaXMgd2hlbiB0aGV5IG5lZWQgYSBkZWxldGlvbidzIHdyaXRlIHRpbWUgKGUuZy4gdG8gY29tcGFyZSBpdCBhZ2FpbnN0IGEgd3JpdGUgdGhleSBhcmUgYWJvdXQgdG8gbWFrZSkuICovXG4gICAgaW5jbHVkZVRvbWJzdG9uZXM/OiBib29sZWFuO1xuICAgIC8qKiBTZWUgR2V0Q29uZmlnLm5vRmFsbGJhY2tzOiBhbnN3ZXIgT05MWSBmcm9tIHRoZSBwcmltYXJ5IHNvdXJjZSAodGhlIG9uZSB3cml0ZXMgd291bGQgdGFyZ2V0KSBpbnN0ZWFkIG9mIGZhbGxpbmcgYmFjayBhY3Jvc3MgdGhlIHJlZHVuZGFudCBzb3VyY2VzLiAqL1xuICAgIG5vRmFsbGJhY2tzPzogYm9vbGVhbjtcbn07XG5cbmV4cG9ydCB0eXBlIENoYW5nZXNBZnRlckNvbmZpZyA9IHtcbiAgICB0aW1lOiBudW1iZXI7XG4gICAgLyoqIE9ubHkga2V5cyByb3V0aW5nIGludG8gb25lIG9mIHRoZXNlIFtzdGFydCwgZW5kKSByYW5nZXMuIE9ubHkgc2Nhbm5pbmcgcGFzc2VzIHRoaXMgLSBpdCBsZXRzIGEgc3RvcmUgc3luY2luZyBhIHBhcnRpYWwgc2hhcmQgYXNrIGZvciBqdXN0IGl0cyBzbGljZS4gKi9cbiAgICByb3V0ZXM/OiBbbnVtYmVyLCBudW1iZXJdW107XG59O1xuXG5leHBvcnQgdHlwZSBTZXRDb25maWcgPSB7XG4gICAgbGFzdE1vZGlmaWVkPzogbnVtYmVyO1xuICAgIC8qKiBNYWtlcyB0aGUgd3JpdGUgYWNjZXB0YWJsZSBvbiBpbW11dGFibGUgdGFyZ2V0czogYW4gZXhpc3RpbmcgcGF0aCBpcyBzaW1wbHkga2VwdCAoaW1tdXRhYmlsaXR5IHdpbnMgLSBub3RoaW5nIGlzIG92ZXJ3cml0dGVuKSBpbnN0ZWFkIG9mIHRoZSB3cml0ZSB0aHJvd2luZy4gUmVxdWlyZXMgbGFzdE1vZGlmaWVkLiBTeW5jaHJvbml6YXRpb24gTVVTVCBwYXNzIHRoaXMgb24gZXZlcnkgcHVzaCAtIGEgcGxhaW4gc2V0IHRocm93cyBvbiBpbW11dGFibGUgdGFyZ2V0cywgd2hpY2ggd291bGQgYWJvcnQgcmVjb25jaWxpYXRpb24gd2hlbmV2ZXIgb25lIHNvdXJjZSBpbiBhIGNoYWluIGlzIGltbXV0YWJsZS4gKi9cbiAgICBmb3JjZVNldEltbXV0YWJsZT86IGJvb2xlYW47XG4gICAgLyoqIFNraXBzIFJFRFVOREFOVCB0YXJnZXQtc2lkZSBzYWZldHkgcmVhZHMgYXJvdW5kIHRoZSB3cml0ZSAoYmFja2JsYXplOiB0aGUgcG9zdC11cGxvYWQgZXhpc3RlbmNlIHBvbGwpLiBJdCBkb2VzIE5PVCBza2lwIGNoZWNrcyB0aGF0IGFyZSB0aGUgdGFyZ2V0J3Mgb25seSBvcmRlcmluZyBndWFyZDogYmFja2JsYXplJ3MgcHJlLXdyaXRlIGNvbXBhcmlzb24gc3RheXMsIGJlY2F1c2UgYjIgaGFzIG5vIHNlcnZlciBvZiBvdXJzIGVuZm9yY2luZyBvbmx5LXRha2UtdGhlLWxhdGVzdCAtIHdpdGhvdXQgaXQgYSBzdGFsZSBwdXNoIGxhbmRzIG92ZXIgYSBuZXdlciB2YWx1ZSBvciB0b21ic3RvbmUgYW5kIGIyJ3Mgc2VsZi1zdGFtcGVkIHVwbG9hZCB0aW1lIGxhdW5kZXJzIGl0IGludG8gdGhlIG5ld2VzdCBjb3B5IGluIHRoZSBzeXN0ZW0gKGdsb2JhbCByZXN1cnJlY3Rpb24pLiBIb3N0ZWQgdGFyZ2V0cyByZS1jaGVjayBzZXJ2ZXItc2lkZSwgc28gdGhlaXIgY2xpZW50LXNpZGUgc2hvcnRjdXRzIGFyZSBzYWZlLiAqL1xuICAgIG5vQ2hlY2tzPzogYm9vbGVhbjtcbiAgICAvKiogU3RvcmUtdG8tc3RvcmUgcHVzaDogdGhlIHJlY2VpdmluZyBub2RlIHdyaXRlcyBwdXJlbHkgdG8gaXRzIG93biBkaXNrIGFuZCBpbmRleCwgd2l0aCBOTyBkb3duc3RyZWFtIGZhbi1vdXQgKHRoZSBwdXNoaW5nIHN0b3JlIG93bnMgcHJvcGFnYXRpb24gLSBmYW5uaW5nIGl0cyBwdXNoZXMgYmFjayBvdXQgaXMgaG93IHdyaXRlIGxvb3BzIGJldHdlZW4gc3RvcmVzIGZvcm0pLiBXaW5kb3cgYW5kIHJvdXRlIEFSRSBzdGlsbCBjaGVja2VkOiB0aGUgc3RhbXAgbXVzdCBmYWxsIGluc2lkZSBvbmUgb2YgdGhlIHJlY2VpdmVyJ3MgY29uZmlndXJlZCB3aW5kb3dzIGFuZCByb3V0ZXMsIHNvIGEgY29uZnVzZWQgcGVlciBjYW5ub3Qgc3R1ZmYgZGF0YSBvbnRvIGEgbm9kZSB0aGF0IHdhcyBuZXZlciBtZWFudCB0byBob2xkIGl0LiBSZXF1aXJlcyBsYXN0TW9kaWZpZWQuICovXG4gICAgaW50ZXJuYWw/OiBib29sZWFuO1xuICAgIC8qKiBXcml0ZXMgbm9ybWFsbHkgZ28gT05MWSB0byB0aGUgd3JpdGUgbm9kZSAodGhlIGZpcnN0IGN1cnJlbnQtd2luZG93IHNvdXJjZSBjb3ZlcmluZyB0aGUga2V5KSwgcmV0cnlpbmcgaXQgZXZlbiB3aGlsZSBpdCBpcyBkb3duIC0gY29uc2lzdGVudCwgYnV0IHVuYXZhaWxhYmxlIHdoZW4gdGhhdCBub2RlIGlzLiBXaXRoIGZhbGxiYWNrcywgdGhlIHdyaXRlIG5vZGUgaXMgc3RpbGwgdHJpZWQgZmlyc3QsIGJ1dCBvbiBmYWlsdXJlIHRoZSB3cml0ZSBsYW5kcyBvbiB0aGUgbmV4dCBjdXJyZW50LXdpbmRvdyBzb3VyY2UgY292ZXJpbmcgdGhlIGtleSAoc3luY2hyb25pemF0aW9uIG1vdmVzIGl0IHRvIHRoZSB3cml0ZSBub2RlIGxhdGVyKSAtIGF2YWlsYWJpbGl0eSBhdCB0aGUgY29zdCBvZiByZWFkcyBwb3NzaWJseSBtaXNzaW5nIHRoZSB3cml0ZSB1bnRpbCBpdCBwcm9wYWdhdGVzLiBTaW5nbGUtc291cmNlIGFyY2hpdmVzIGlnbm9yZSB0aGUgZmxhZy4gKi9cbiAgICBmYWxsYmFja3M/OiBib29sZWFuO1xufTtcblxuLy8gY3JlYXRlVGltZSBpcyBhIG1pc25vbWVyIGtlcHQgZm9yIGNvbXBhdGliaWxpdHkg4oCUIGl0IGlzIHJlYWxseSB0aGUgTEFTVC1XUklURSB0aW1lLCBzYW1lIGFzIGdldEluZm8ncyB3cml0ZVRpbWUuIE5laXRoZXIgQmFja2JsYXplIG5vciBvdXIgcmVtb3RlIHN0b3JhZ2UgdHJhY2tzIGEgZGlzdGluY3QgY3JlYXRpb24gZGF0ZTogZWFjaCB3cml0ZSBzdGFtcHMgYSBmcmVzaCB0aW1lc3RhbXAgb24gdGhlIGN1cnJlbnQgdmVyc2lvbiwgc28gYm90aCBmaWVsZHMgYXJlIGp1c3QgXCJ3aGVuIHRoZSBieXRlcyBzZXJ2ZWQgYnkgZ2V0KCkgd2VyZSBtb3N0IHJlY2VudGx5IHdyaXR0ZW5cIi5cbmV4cG9ydCB0eXBlIEFyY2hpdmVGaWxlSW5mbyA9IHsgcGF0aDogc3RyaW5nOyBjcmVhdGVUaW1lOiBudW1iZXI7IHNpemU6IG51bWJlciB9O1xuXG4vLyBBbiBpbi1wcm9ncmVzcyBiYWNrZ3JvdW5kIHN5bmNocm9uaXphdGlvbiB0YXNrIChzZWUgQXJjaGl2ZXNDb25maWcuc3luY2luZylcbmV4cG9ydCB0eXBlIFN5bmNBY3Rpdml0eSA9IHtcbiAgICAvLyBBIG1ldGFkYXRhIHNjYW4gaXMgYSBzaW5nbGUgbGlzdGluZyBjYWxsLCBzbyBpdCBoYXMgbm8gaW5jcmVtZW50YWwgcHJvZ3Jlc3MgLSBqdXN0IHRoYXQgaXQncyBydW5uaW5nIGFuZCBzaW5jZSB3aGVuLiBBIGZ1bGwgc3luYyBrbm93cyBpdHMgZXhhY3QgZmlsZS9ieXRlIHByb2dyZXNzLlxuICAgIHR5cGU6IFwibWV0YWRhdGFTY2FuXCIgfCBcImZ1bGxTeW5jXCI7XG4gICAgc291cmNlRGVidWdOYW1lOiBzdHJpbmc7XG4gICAgc3RhcnRUaW1lOiBudW1iZXI7XG4gICAgZG9uZUZpbGVzPzogbnVtYmVyO1xuICAgIHRvdGFsRmlsZXM/OiBudW1iZXI7XG4gICAgZG9uZUJ5dGVzPzogbnVtYmVyO1xuICAgIHRvdGFsQnl0ZXM/OiBudW1iZXI7XG59O1xuXG5leHBvcnQgdHlwZSBBcmNoaXZlc0NvbmZpZyA9IHtcbiAgICAvLyBXaGV0aGVyIGdldENoYW5nZXNBZnRlcjIgaXMgbmF0aXZlbHkgaW5kZXgtYmFja2VkIChmYXN0IGNoYW5nZSBwb2xsaW5nOyBldmVyeSBiYWNrZW5kIHN0aWxsIHNlcnZlcyBpdCwgYnV0IHRoZSBvdGhlcnMgZW11bGF0ZSBpdCB3aXRoIGEgZnVsbCBsaXN0aW5nKVxuICAgIHN1cHBvcnRzQ2hhbmdlc0FmdGVyPzogYm9vbGVhbjtcbiAgICAvLyBUaGUgYnVja2V0J3MgZnVsbCByb3V0aW5nIGNvbmZpZyAoUk9VVElOR19GSUxFKS4gQWJzZW50IGZvciBzb3VyY2VzIHRoYXQgZG9uJ3QgaGF2ZSBvbmUgKGEgYmFyZSBkaXNrIHNvdXJjZSwgb3IgYSBidWNrZXQgdGhhdCBkb2Vzbid0IGV4aXN0IHlldCkuXG4gICAgcmVtb3RlQ29uZmlnPzogUmVtb3RlQ29uZmlnO1xuICAgIC8vIExpdmUgaW5kZXggdG90YWxzICh0b21ic3RvbmVzIGV4Y2x1ZGVkKSwga2VwdCB1cCB0byBkYXRlIGluIG1lbW9yeSBvbiBldmVyeSBtdXRhdGlvbiBhbmQgcmVjb21wdXRlZCBvbiBsb2FkIC0gc28gYW55IGRyaWZ0IGhlYWxzIG9uIHJlc3RhcnRcbiAgICBpbmRleD86IHsgZmlsZUNvdW50OiBudW1iZXI7IGJ5dGVDb3VudDogbnVtYmVyIH07XG4gICAgLy8gVGhlIHNhbWUgdG90YWxzIGJyb2tlbiBkb3duIGJ5IHdoaWNoIHNvdXJjZSBjdXJyZW50bHkgaG9sZHMgZWFjaCBmaWxlJ3MgYnl0ZXMgKHRoZSBmaXJzdCBlbnRyeSBpcyB0aGUgc2VydmVyJ3Mgb3duIGRpc2spXG4gICAgaW5kZXhTb3VyY2VzPzogeyBkZWJ1Z05hbWU6IHN0cmluZzsgZmlsZUNvdW50OiBudW1iZXI7IGJ5dGVDb3VudDogbnVtYmVyIH1bXTtcbiAgICAvLyBUaGUgc2VydmVyJ3MgY29uZmlndXJlZCByZWFkZXJEaXNrTGltaXQsIHdoZW4gaXQgcnVucyBhcyBhIGJvdW5kZWQgcmVhZCBjYWNoZVxuICAgIHJlYWRlckRpc2tMaW1pdD86IG51bWJlcjtcbiAgICAvLyBCYWNrZ3JvdW5kIHN5bmNocm9uaXphdGlvbiBjdXJyZW50bHkgaW4gcHJvZ3Jlc3MgKGVtcHR5IHdoZW4gaWRsZSlcbiAgICBzeW5jaW5nPzogU3luY0FjdGl2aXR5W107XG59O1xuXG4vLyBBIHN5bmNocm9uaXphdGlvbiBzb3VyY2Ugb2YgYSBCbG9iU3RvcmUgKHdoaWNoIHN5bmNocm9uaXplcyBhbiBpbmRleCArIGxvY2FsIGNhY2hlIGZyb20gdGhlbSlcbmV4cG9ydCB0eXBlIEFyY2hpdmVzU291cmNlID0ge1xuICAgIHNvdXJjZTogSUFyY2hpdmVzO1xuICAgIC8qKiBUaGUgcGVyc2lzdGVudCBpZGVudGl0eSBvZiB0aGUgZW5kcG9pbnQ6IGl0cyByb3V0aW5nIFVSTCAoaG9zdGVkL2JhY2tibGF6ZSksIG9yIHRoZSBkaXNrIGZvbGRlciBwYXRoIGZvciB0aGUgYmFzZSBkaXNrIHNvdXJjZS4gVGhlIHN0b3JlIHBlcnNpc3RzIHRoaXMgKHZpYSBpdHMgYXBwZW5kLW9ubHkgc291cmNlcyBsaXN0KSBhcyBJbmRleEVudHJ5LnNvdXJjZXNMaXN0SW5kZXgsIHNvIGl0IG11c3QgbWVhbiB0aGUgc2FtZSBlbmRwb2ludCBmb3JldmVyLiAqL1xuICAgIHVybDogc3RyaW5nO1xuICAgIC8vIEZyb20gdGhlIHNvdXJjZSdzIENvbW1vbkNvbmZpZy4gVGhlIHdpbmRvdyByb3V0ZXMgV1JJVEVTOiBvbmNlIGl0cyBlbmQgaXMgcGFzdCAoc2VlIHdpbmRvd0FjY2VwdHNXcml0ZXMpIHRoZSBzb3VyY2Ugc3RvcHMgcmVjZWl2aW5nIHdyaXRlcyBlbnRpcmVseSAtIGl0IGp1c3Qgc3RvcHMgZ3Jvd2luZy4gSXQgZG9lcyBOT1QgZmlsdGVyIHNjYW5uaW5nOiBhIHNjYW4gaXMgdXMgYXNraW5nIHRoZSBzb3VyY2Ugd2hhdCBpdCBhbHJlYWR5IGhvbGRzLCBhbmQgZXhpc3RpbmcgdmFsdWVzIHN5bmNocm9uaXplIHJlZ2FyZGxlc3Mgb2YgdGhlaXIgd3JpdGUgdGltZXMgKHRoZSBzYW1lIHJlYXNvbmluZyB0aGF0IGxldHMgc3luY2hyb25pemF0aW9uIGlnbm9yZSB0aGUgaW1tdXRhYmxlIGZsYWcpLlxuICAgIHZhbGlkV2luZG93OiBbbnVtYmVyLCBudW1iZXJdO1xuICAgIC8vIEZyb20gdGhlIHNvdXJjZSdzIENvbW1vbkNvbmZpZyAoaW50ZXJzZWN0ZWQgd2l0aCB0aGUgb3duaW5nIHN0b3JlJ3Mgb3duIHJvdXRlKTogb25seSBrZXlzIHJvdXRpbmcgaW50byBbc3RhcnQsIGVuZCkgYXJlIGFjY2VwdGVkIGZyb20gdGhpcyBzb3VyY2UncyBzY2FucyBhbmQgc2VudCB0byBpdCBpbiB3cml0ZXMvcmVjb25jaWxpYXRpb24uIFRoZSByb3V0aW5nIGZpbGUgaXMgZXhlbXB0IC0gY29uZmlnIGZsb3dzIGV2ZXJ5d2hlcmUuIEFic2VudCA9IGFsbCBrZXlzLlxuICAgIHJvdXRlPzogW251bWJlciwgbnVtYmVyXTtcbiAgICAvLyBGcm9tIHRoZSBzb3VyY2UncyBDb21tb25Db25maWc7IHNlZSB0aGVyZS5cbiAgICBub0Z1bGxTeW5jPzogYm9vbGVhbjtcbiAgICAvLyBGcm9tIHRoZSBzb3VyY2UncyBDb21tb25Db25maWc6IGEgZGVwbG95IHN3aXRjaG92ZXIncyB0ZW1wb3JhcnkgYWx0ZXJuYXRlLXBvcnQgZW50cnkuIE9uY2UgaXRzIHdpbmRvdyBpcyBwYXN0LCB0aGUgcG9ydCBpdCBwb2ludHMgYXQgaXMgZ29uZSBmb3IgZ29vZCAtIHNvIGl0IGlzIG5ldmVyIHNjYW5uZWQgdGhlbiwgYW5kIHNjYW4gZmFpbHVyZXMgYXJlIG5ldmVyIHJldHJpZWQuXG4gICAgaW50ZXJtZWRpYXRlPzogYm9vbGVhbjtcbiAgICAvLyBUaGUgcm91dGluZy1jb25maWcgZW50cnkgdGhpcyBzb3VyY2Ugd2FzIGJ1aWx0IGZyb20gKGFic2VudCBmb3IgdGhlIGJhc2UgZGlzayBzb3VyY2UpLiBJdHMgYHR5cGVgIGRlY2lkZXMgZmFzdC13cml0ZSBmbHVzaCB0aW1pbmc6IHR5cGUtXCJyZW1vdGVcIiBkb3duc3RyZWFtIHNvdXJjZXMgKG91ciBvd24gc3RvcmFnZSBzZXJ2ZXJzKSBmbHVzaCBxdWlja2x5IChjaGVhcCwgYW5kIHdlIHdhbnQgY3Jvc3Mtbm9kZSByZWR1bmRhbmN5IGZhc3QpLCB3aGlsZSBvdGhlcnMgKGUuZy4gYmFja2JsYXplKSBrZWVwIHRoZSBmdWxsIHdyaXRlRGVsYXkgc28gZXhwZW5zaXZlIGV4dGVybmFsIHdyaXRlcyBzdGF5IGNvYWxlc2NlZC4gVGhlIHdpbmRvdy9yb3V0ZSBPTiB0aGlzIGNvbmZpZyBhcmUgdGhlIFNPVVJDRSdzIG93bjsgQXJjaGl2ZXNTb3VyY2UudmFsaWRXaW5kb3cvcm91dGUgYXJlIHdoYXQgdGhlIG93bmluZyBzdG9yZSBhY3R1YWxseSB1c2VzIChyb3V0ZSBpcyBpbnRlcnNlY3RlZCB3aXRoIHRoZSBzdG9yZSdzIHJvdXRlKS5cbiAgICBzb3VyY2VDb25maWc/OiBTb3VyY2VDb25maWc7XG4gICAgLy8gU3RhYmxlIGlkZW50aXR5IG9mIHRoZSB1bmRlcmx5aW5nIGVuZHBvaW50IChpdHMgY29uZmlnIHdpdGggd2luZG93cy9yb3V0ZXMgc3RyaXBwZWQpIC0gaG93IEJsb2JTdG9yZS51cGRhdGVTb3VyY2VzIHJlY29nbml6ZXMgYSBzb3VyY2UgYWNyb3NzIGNvbmZpZyBjaGFuZ2VzIHNvIGl0IGNhbiB1cGRhdGUgaXQgaW4gcGxhY2UgaW5zdGVhZCBvZiByZW1vdmluZyBhbmQgcmUtYWRkaW5nIGl0XG4gICAgaWRlbnRpdHk/OiBzdHJpbmc7XG59O1xuXG4vLyBFcnJvciBtYXJrZXIgYSBzZXJ2ZXIgaW5jbHVkZXMgd2hlbiBhIGZyZXNobHktc3RhbXBlZCB3cml0ZSByZWFjaGVzIGl0IG91dHNpZGUgaXRzIHZhbGlkIHdpbmRvd3MgKHRoZSBjbGllbnQgcmVzb2x2ZWQgaXRzIHRhcmdldCwgdGhlbiB0aW1lIGNyb3NzZWQgYSB3aW5kb3cgYm91bmRhcnkgYmVmb3JlIHRoZSB3cml0ZSBsYW5kZWQpLiBDbGllbnRzIGRldGVjdCB0aGlzIG1hcmtlciBhbmQgcmUtcmVzb2x2ZSB0aGUgY3VycmVudGx5LXZhbGlkIHNvdXJjZSwgcmV0cnlpbmcgT05DRSAtIGJvdW5kYXJpZXMgYXJlIGZhciBhcGFydCwgc28gaGl0dGluZyBpdCB0d2ljZSBpbiBvbmUgYXR0ZW1wdCBtZWFucyBzb21ldGhpbmcgaXMgYWN0dWFsbHkgd3JvbmcuXG5leHBvcnQgY29uc3QgU1RPUkFHRV9XUk9OR19WQUxJRF9XSU5ET1cgPSBcIlJFTU9URV9TVE9SQUdFX1dST05HX1ZBTElEX1dJTkRPV19hN2MxZjA0ZVwiO1xuXG4vLyBFcnJvciBtYXJrZXIgYSBzZXJ2ZXIgaW5jbHVkZXMgd2hlbiBhIGZyZXNobHktc3RhbXBlZCB3cml0ZSdzIGtleSByb3V0ZXMgb3V0c2lkZSB0aGUgc2hhcmRzIHRoaXMgc2VydmVyIGhhbmRsZXMgKHRoZSBjbGllbnQncyBjb25maWcgZGlzYWdyZWVzIHdpdGggdGhlIHNlcnZlcidzIC0gY2xpZW50cyByZS1yZXNvbHZlIG9uY2UpXG5leHBvcnQgY29uc3QgU1RPUkFHRV9XUk9OR19ST1VURSA9IFwiUkVNT1RFX1NUT1JBR0VfV1JPTkdfUk9VVEVfYzk0ZDJlMTdcIjtcblxuZXhwb3J0IGNvbnN0IEZVTExfUk9VVEU6IFtudW1iZXIsIG51bWJlcl0gPSBbMCwgMV07XG5cbi8vIEEga2V5IGNvbnRhaW5pbmcgdGhpcyBzZW50aW5lbCBkb2Vzbid0IGhhdmUgYSBmaXhlZCBzaGFyZDogc2V0VmFyaWFibGVTaGFyZCBwaWNrcyB0aGUgKGxvd2VzdCBsYXRlbmN5LCB1cCkgd3JpdGUgc2hhcmQsIGFwcGVuZHMgXCJfPHZhbHVlIGluIHRoZSBzaGFyZCdzIHJvdXRlPlwiIGRpcmVjdGx5IGFmdGVyIHRoZSBzZW50aW5lbCwgYW5kIHJldHVybnMgdGhlIG1hdGVyaWFsaXplZCBrZXkuIGdldFJvdXRlIHRyZWF0cyB0aGF0IHN1ZmZpeCBhcyBhIGNvbXBsZXRlIHJvdXRlIG92ZXJyaWRlLlxuZXhwb3J0IGNvbnN0IFZBUklBQkxFX1NIQVJEID0gXCJWQVJJQUJMRV9TSEFSRF9mMDIzNGpmYWgwOGZneWhmZ3lzc2Rkczgzbm1wXCI7XG4vLyBObyBncmFjZSBwYXN0IHRoZSBlbmQ6IGEgd2luZG93IGJvdW5kYXJ5IGlzIGEgaGFyZCBoYW5kb2ZmIChjbGllbnRzIHJldHJ5IGEgcmVqZWN0ZWQgd3JpdGUgYWdhaW5zdCB0aGUgbmV3bHktdmFsaWQgc291cmNlLCBzbyBsZW5pZW5jeSBoZXJlIHdvdWxkIG9ubHkgZGVzeW5jaHJvbml6ZSB0aGUgaGFuZG9mZilcbi8vICAtIFdyaXRpbmcgdG8gb2xkZXIgdmFsaWQgc3RhdGUgd2luZG93cyBpcyBmaW5lLCB0aG91Z2guIFdlIG5lZWQgdGhpcyB0byBpbmdlc3QgdGhlIG9sZCBkYXRhIHdoZW4gd2UncmUgc3luY2hyb25pemluZyBub2RlcyB0byBnZXQgdGhlbSB1cCB0byBkYXRlIGFueXdheS4gXG5leHBvcnQgZnVuY3Rpb24gd2luZG93QWNjZXB0c1dyaXRlcyh2YWxpZFdpbmRvdzogW251bWJlciwgbnVtYmVyXSB8IHVuZGVmaW5lZCk6IGJvb2xlYW4ge1xuICAgIGlmICghdmFsaWRXaW5kb3cpIHJldHVybiB0cnVlO1xuICAgIHJldHVybiB2YWxpZFdpbmRvd1sxXSA+IERhdGUubm93KCk7XG59XG5cbmNvbnN0IExBUkdFX0NPUFlfVEhSRVNIT0xEID0gNjQgKiAxMDI0ICogMTAyNDtcbmNvbnN0IExBUkdFX0NPUFlfQ0hVTksgPSAzMiAqIDEwMjQgKiAxMDI0O1xuXG4vLyBBYm92ZSB0aGlzLCBzZXQgdHJhbnNwYXJlbnRseSBzdHJlYW1zIHRocm91Z2ggc2V0TGFyZ2VGaWxlOiBvbmUgZ2lhbnQgd2lyZSBtZXNzYWdlIHdvdWxkIGV4Y2VlZCB0aGUgdHJhbnNwb3J0IGxpbWl0IGFuZCBsYWcgZXZlcnkgb3RoZXIgY2xpZW50IHNoYXJpbmcgdGhlIGNvbm5lY3Rpb25cbmV4cG9ydCBjb25zdCBMQVJHRV9TRVRfVEhSRVNIT0xEID0gOCAqIDEwMjQgKiAxMDI0O1xuXG4vKiogQSBnZXROZXh0RGF0YSBzdHJlYW0gb3ZlciBhbiBpbi1tZW1vcnkgYnVmZmVyLCBpbiBMQVJHRV9TRVRfVEhSRVNIT0xEIHNsaWNlcyAtIGhvdyBzZXQgdHJhbnNwYXJlbnRseSBiZWNvbWVzIHNldExhcmdlRmlsZSBmb3IgbGFyZ2UgYnVmZmVycy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidWZmZXJDaHVua1N0cmVhbShkYXRhOiBCdWZmZXIpOiAoKSA9PiBQcm9taXNlPEJ1ZmZlciB8IHVuZGVmaW5lZD4ge1xuICAgIGxldCBvZmZzZXQgPSAwO1xuICAgIHJldHVybiBhc3luYyAoKSA9PiB7XG4gICAgICAgIGlmIChvZmZzZXQgPj0gZGF0YS5sZW5ndGgpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIGxldCBjaHVuayA9IGRhdGEuc3ViYXJyYXkob2Zmc2V0LCBvZmZzZXQgKyBMQVJHRV9TRVRfVEhSRVNIT0xEKTtcbiAgICAgICAgb2Zmc2V0ICs9IGNodW5rLmxlbmd0aDtcbiAgICAgICAgcmV0dXJuIGNodW5rO1xuICAgIH07XG59XG5cbi8qKiBDb3BpZXMgb25lIGZpbGUgYmV0d2VlbiB0d28gYXJjaGl2ZXMuIFNtYWxsIGZpbGVzIGdvIGFzIGEgc2luZ2xlIGdldDIrc2V0OyBwYXN0IExBUkdFX0NPUFlfVEhSRVNIT0xEIHRoZSBjb3B5IHN0cmVhbXMgdGhyb3VnaCBzZXRMYXJnZUZpbGUgaW4gTEFSR0VfQ09QWV9DSFVOSyByYW5nZWQgcmVhZHMsIHNvIHRoZSB3aG9sZSBmaWxlIGlzIG5ldmVyIGluIG1lbW9yeS4gc2l6ZS93cml0ZVRpbWUgdXN1YWxseSBjb21lIGZyb20gdGhlIGNhbGxlcidzIG1ldGFkYXRhIHNjYW47IHdoZW4gZWl0aGVyIGlzIG9taXR0ZWQsIGdldEluZm8gZmlsbHMgdGhlbSBpbi4gUmV0dXJucyB0aGUgY29waWVkIGZpbGUncyBpbmZvLCBvciB1bmRlZmluZWQgd2hlbiB0aGUgc291cmNlIGRvZXNuJ3QgaGF2ZSB0aGUgZmlsZS4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjb3B5QXJjaGl2ZUZpbGUoY29uZmlnOiB7XG4gICAgZnJvbTogSUFyY2hpdmVzO1xuICAgIHRvOiBJQXJjaGl2ZXM7XG4gICAgcGF0aDogc3RyaW5nO1xuICAgIHNpemU/OiBudW1iZXI7XG4gICAgd3JpdGVUaW1lPzogbnVtYmVyO1xuICAgIGZvcmNlU2V0SW1tdXRhYmxlPzogYm9vbGVhbjtcbiAgICBub0NoZWNrcz86IGJvb2xlYW47XG4gICAgaW50ZXJuYWw/OiBib29sZWFuO1xuICAgIG5vRmFsbGJhY2tzPzogYm9vbGVhbjtcbn0pOiBQcm9taXNlPHsgd3JpdGVUaW1lOiBudW1iZXI7IHNpemU6IG51bWJlciB9IHwgdW5kZWZpbmVkPiB7XG4gICAgbGV0IHsgZnJvbSwgdG8sIHBhdGggfSA9IGNvbmZpZztcbiAgICBsZXQgc2l6ZSA9IGNvbmZpZy5zaXplO1xuICAgIGxldCB3cml0ZVRpbWUgPSBjb25maWcud3JpdGVUaW1lO1xuICAgIGlmIChzaXplID09PSB1bmRlZmluZWQgfHwgd3JpdGVUaW1lID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgbGV0IGluZm8gPSBhd2FpdCBmcm9tLmdldEluZm8ocGF0aCwgeyBub0ZhbGxiYWNrczogY29uZmlnLm5vRmFsbGJhY2tzIH0pO1xuICAgICAgICBpZiAoIWluZm8pIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIHNpemUgPSBpbmZvLnNpemU7XG4gICAgICAgIHdyaXRlVGltZSA9IGluZm8ud3JpdGVUaW1lO1xuICAgIH1cbiAgICBpZiAoc2l6ZSA8PSBMQVJHRV9DT1BZX1RIUkVTSE9MRCkge1xuICAgICAgICBsZXQgcmVzdWx0ID0gYXdhaXQgZnJvbS5nZXQyKHBhdGgsIHsgaW50ZXJuYWw6IGNvbmZpZy5pbnRlcm5hbCwgbm9GYWxsYmFja3M6IGNvbmZpZy5ub0ZhbGxiYWNrcyB9KTtcbiAgICAgICAgLy8gRW1wdHkgY291bnRzIGFzIGFic2VudCwgbmV2ZXIgYXMgY29udGVudCB0byBjb3B5OiBhbiBlbXB0eSBmaWxlIElTIGEgZGVsZXRpb24sIHNldCByZWZ1c2VzIGVtcHR5IGJ1ZmZlcnMsIGFuZCBkZWxldGlvbnMgdHJhdmVsIHRocm91Z2ggdGhlaXIgb3duIHBhdGggKGRlbCAvIHNjYW4gdG9tYnN0b25lcylcbiAgICAgICAgaWYgKCFyZXN1bHQgfHwgIXJlc3VsdC5kYXRhIHx8ICFyZXN1bHQuZGF0YS5sZW5ndGgpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIGF3YWl0IHRvLnNldChwYXRoLCByZXN1bHQuZGF0YSwgeyBsYXN0TW9kaWZpZWQ6IHJlc3VsdC53cml0ZVRpbWUsIGZvcmNlU2V0SW1tdXRhYmxlOiBjb25maWcuZm9yY2VTZXRJbW11dGFibGUsIG5vQ2hlY2tzOiBjb25maWcubm9DaGVja3MsIGludGVybmFsOiBjb25maWcuaW50ZXJuYWwgfSk7XG4gICAgICAgIHJldHVybiB7IHdyaXRlVGltZTogcmVzdWx0LndyaXRlVGltZSwgc2l6ZTogcmVzdWx0LmRhdGEubGVuZ3RoIH07XG4gICAgfVxuICAgIC8vIENvbnN0cyBzbyB0aGUgY2xvc3VyZSBrZWVwcyB0aGUgbmFycm93ZWQgdHlwZXNcbiAgICBjb25zdCB0b3RhbFNpemUgPSBzaXplO1xuICAgIGNvbnN0IGZpbmFsV3JpdGVUaW1lID0gd3JpdGVUaW1lO1xuICAgIGxldCBvZmZzZXQgPSAwO1xuICAgIGF3YWl0IHRvLnNldExhcmdlRmlsZSh7XG4gICAgICAgIHBhdGgsXG4gICAgICAgIGxhc3RNb2RpZmllZDogZmluYWxXcml0ZVRpbWUsXG4gICAgICAgIGdldE5leHREYXRhOiBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBpZiAob2Zmc2V0ID49IHRvdGFsU2l6ZSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGxldCBlbmQgPSBNYXRoLm1pbihvZmZzZXQgKyBMQVJHRV9DT1BZX0NIVU5LLCB0b3RhbFNpemUpO1xuICAgICAgICAgICAgbGV0IGRhdGEgPSBhd2FpdCBmcm9tLmdldChwYXRoLCB7IHJhbmdlOiB7IHN0YXJ0OiBvZmZzZXQsIGVuZCB9LCBpbnRlcm5hbDogY29uZmlnLmludGVybmFsLCBub0ZhbGxiYWNrczogY29uZmlnLm5vRmFsbGJhY2tzIH0pO1xuICAgICAgICAgICAgaWYgKCFkYXRhIHx8ICFkYXRhLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgUmFuZ2VkIHJlYWQgb2YgJHtKU09OLnN0cmluZ2lmeShwYXRoKX0gZnJvbSAke2Zyb20uZ2V0RGVidWdOYW1lKCl9IHJldHVybmVkICR7ZGF0YSAmJiBkYXRhLmxlbmd0aCB8fCBcIm5vdGhpbmdcIn0gYXQgJHtvZmZzZXR9LSR7ZW5kfSAoZXhwZWN0ZWQgJHtlbmQgLSBvZmZzZXR9IGJ5dGVzIG9mIGEgJHt0b3RhbFNpemV9IGJ5dGUgZmlsZSAtIGl0IGNoYW5nZWQgb3IgdmFuaXNoZWQgbWlkLWNvcHkpYCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvZmZzZXQgKz0gZGF0YS5sZW5ndGg7XG4gICAgICAgICAgICByZXR1cm4gZGF0YTtcbiAgICAgICAgfSxcbiAgICB9KTtcbiAgICByZXR1cm4geyB3cml0ZVRpbWU6IGZpbmFsV3JpdGVUaW1lLCBzaXplOiB0b3RhbFNpemUgfTtcbn1cblxuZXhwb3J0IHR5cGUgQXJjaGl2ZXNTeW5jU291cmNlU3RhdHVzID0ge1xuICAgIGRlYnVnTmFtZTogc3RyaW5nO1xuICAgIHZhbGlkV2luZG93OiBbbnVtYmVyLCBudW1iZXJdO1xuICAgIHJvdXRlPzogW251bWJlciwgbnVtYmVyXTtcbiAgICBub0Z1bGxTeW5jPzogYm9vbGVhbjtcbiAgICBzdXBwb3J0c0NoYW5nZXNBZnRlcjogYm9vbGVhbjtcbiAgICBpbml0aWFsU2NhbkNvbXBsZXRlOiBib29sZWFuO1xuICAgIC8vIEZpbGVzIHNlZW4gaW4gdGhpcyBzb3VyY2UncyBzY2FucyAvIGNoYW5nZSBwb2xscyBzbyBmYXJcbiAgICBzY2FubmVkQ291bnQ6IG51bWJlcjtcbn07XG5leHBvcnQgdHlwZSBBcmNoaXZlc1N5bmNTdGF0dXMgPSB7XG4gICAgYWxsU2NhbnNDb21wbGV0ZTogYm9vbGVhbjtcbiAgICAvLyBOdW1iZXIgb2YgZmlsZXMgaW4gdGhlIGluZGV4XG4gICAgaW5kZXhTaXplOiBudW1iZXI7XG4gICAgc291cmNlczogQXJjaGl2ZXNTeW5jU291cmNlU3RhdHVzW107XG59O1xuXG4vLyBOT1RFOiBXZSBkb24ndCBwcmVzZW50bHkgaGF2ZSBhbiBhcHBlbmQgZnVuY3Rpb24gaGVyZSBiZWNhdXNlIGEgc3VycHJpc2luZyBudW1iZXIgb2Ygc3RvcmFnZSBzeXN0ZW1zIGRvbid0IHN1cHBvcnQgaXQgKGJhY2tibGF6ZSwgZmlsZSBzeXN0ZW0gYXBpKS4gSXQgd291bGQgYWxzbyBjb21wbGljYXRlIHRoaW5ncyBhcyBub3cgdGhlcmUgbmVlZHMgdG8gYmUgcmVhbGx5IGEgc2luZ2xlIHNvdXJjZSBvZiB0cnV0aCBvZiBhIGZpbGUsIGFuZCBpZiB5b3UgYXBwZW5kIHRvIHRoZSB3cm9uZyBzaW5nbGUgc291cmNlIG9mIHRydXRoLCB0aGluZ3MganVzdCBiZWNvbWUgdmVyeSBjb21wbGljYXRlZC4gXG5leHBvcnQgaW50ZXJmYWNlIElBcmNoaXZlcyB7XG4gICAgZ2V0RGVidWdOYW1lKCk6IHN0cmluZztcbiAgICAvKiogV2hldGhlciB3cml0ZXMgd291bGQgYmUgYWNjZXB0ZWQgKGNyZWRlbnRpYWxzIGV4aXN0LCB0aGUgYWNjb3VudCB0cnVzdHMgdGhpcyBtYWNoaW5lLCBldGMpLiBDaGVja2VkIHdpdGhvdXQgd3JpdGluZyBhbnl0aGluZy4gKi9cbiAgICBoYXNXcml0ZUFjY2VzcygpOiBQcm9taXNlPGJvb2xlYW4+O1xuICAgIC8qKlxuICAgICAqIFJlYWRzIGF1dG9tYXRpY2FsbHkgZmFsbCBiYWNrIGFjcm9zcyB0aGUgcmVkdW5kYW50IHNvdXJjZXMgdW5sZXNzIGNvbmZpZy5ub0ZhbGxiYWNrcyBpcyBzZXQuXG4gICAgICogQSBmYWxsYmFjayBjb3B5IGNhbiBsYWcgdGhlIHdyaXRlIHRhcmdldCwgc28gYSBjYWxsZXIgcmVhZGluZyBzdGF0ZSBpbiBvcmRlciB0byBtdXRhdGUgaXRcbiAgICAgKiAoZS5nLiB4KyspLCB3aGVyZSBhY3Rpbmcgb24gcHJldmlvdXMgc3RhdGUgd291bGQgY2F1c2UgYmlnIGlzc3Vlcywgc2hvdWxkIHBhc3Mgbm9GYWxsYmFja3MgLVxuICAgICAqIGFuZCB0cnkvY2F0Y2ggdGhlIHJlYWQsIGhhbmRsaW5nIHRoZSBjYXRjaCBjYXNlIChhIGRvd24gcHJpbWFyeSBpcyByZXRyaWVkIGZvciBhIHdoaWxlLCB0aGVuXG4gICAgICogdGhyb3dzIGluc3RlYWQgb2YgZGVncmFkaW5nIHRvIGEgc3RhbGUgY29weSkuXG4gICAgICovXG4gICAgZ2V0KGZpbGVOYW1lOiBzdHJpbmcsIGNvbmZpZz86IEdldENvbmZpZyk6IFByb21pc2U8QnVmZmVyIHwgdW5kZWZpbmVkPjtcbiAgICAvKiogU2VlIGdldCBmb3IgdGhlIGZhbGxiYWNrIHNlbWFudGljcyAoYW5kIHdoZW4gdG8gcGFzcyBub0ZhbGxiYWNrcykuIHVybCBpcyB0aGUgY29uZmlnIFVSTCBvZiB0aGUgc291cmNlIHRoYXQgYW5zd2VyZWQgLSB0aGUgYXV0aG9yaXR5IHRoZSBkYXRhIChvciB0aGUgXCJkb2VzIG5vdCBleGlzdFwiKSBjYW1lIGZyb20uIE11bHRpLXNvdXJjZSBpbXBsZW1lbnRhdGlvbnMgKEFyY2hpdmVzQ2hhaW4pIEFMV0FZUyByZXR1cm4gYW4gb2JqZWN0OiB3aGVuIHRoZSB2YWx1ZSBkb2Vzbid0IGV4aXN0IHRoZXJlIGlzIHN0aWxsIGEgc2VydmVyIHNheWluZyBpdCBkb2Vzbid0IGV4aXN0LCBzbyB0aGV5IHJldHVybiB7IHVybCB9IGFsb25lIHJhdGhlciB0aGFuIHVuZGVmaW5lZC4gU2luZ2xlLXNvdXJjZSBiYWNrZW5kcyByZXR1cm4gdW5kZWZpbmVkIGZvciBhYnNlbnQgKHRoZXkgQVJFIHRoZSBhdXRob3JpdHkpLiAqL1xuICAgIGdldDIoZmlsZU5hbWU6IHN0cmluZywgY29uZmlnPzogR2V0Q29uZmlnKTogUHJvbWlzZTx7IGRhdGE6IEJ1ZmZlcjsgd3JpdGVUaW1lOiBudW1iZXI7IHNpemU6IG51bWJlcjsgdXJsPzogc3RyaW5nIH0gfCB7IGRhdGE/OiB1bmRlZmluZWQ7IHdyaXRlVGltZT86IHVuZGVmaW5lZDsgc2l6ZT86IHVuZGVmaW5lZDsgdXJsOiBzdHJpbmcgfSB8IHVuZGVmaW5lZD47XG4gICAgLyoqXG4gICAgICogbGFzdE1vZGlmaWVkIHN0YW1wcyB0aGUgd3JpdGUgd2l0aCB0aGF0IGxhc3Qtd3JpdGUgdGltZSBpbnN0ZWFkIG9mIG5vdy4gSWYgaXQgaXMgT0xERVIgdGhhblxuICAgICAqIHRoZSBmaWxlJ3MgY3VycmVudCBsYXN0LXdyaXRlIHRpbWUgdGhlIHdyaXRlIG5vLW9wcyAoc28gZGVsYXllZCAvIHN5bmNocm9uaXplZCB3cml0ZXMgY2FuXG4gICAgICogbmV2ZXIgY2xvYmJlciBuZXdlciBkYXRhKS4gVGltZXMgbW9yZSB0aGFuIDE1IG1pbnV0ZXMgaW4gdGhlIGZ1dHVyZSBhcmUgcmVqZWN0ZWQuXG4gICAgICpcbiAgICAgKiBSZXR1cm5zIHRoZSBmdWxsIGtleSBhY3R1YWxseSB3cml0dGVuIC0gaWRlbnRpY2FsIHRvIGZpbGVOYW1lLCBFWENFUFQgZm9yIGtleXMgY29udGFpbmluZ1xuICAgICAqIFZBUklBQkxFX1NIQVJELCB3aGVyZSB0aGUgc2hhcmQgdmFsdWUgaXMgbWF0ZXJpYWxpemVkIGludG8gdGhlIGtleSAocGlja2VkIGJ5IHNoYXJkIGxhdGVuY3ksXG4gICAgICogc2VlIEFyY2hpdmVzQ2hhaW4pIGFuZCB0aGUgY2FsbGVyIG5lZWRzIHRoZSByZXR1cm5lZCBrZXkgdG8gZXZlciByZWFkIHRoZSB2YWx1ZSBiYWNrLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIFRIUk9XUyBvbiBhbiBlbXB0eSBidWZmZXI6IGFuIGVtcHR5IGZpbGUgSVMgYSBkZWxldGlvbiBpbiB0aGlzIHN5c3RlbSAodGhlIHRvbWJzdG9uZSksIHNvIGFcbiAgICAgKiBzZXQtZW1wdHkgd291bGQgcmVhZCBiYWNrIGFzIFwidGhlIGZpbGUgaXMgZ29uZVwiIC0gd2hpY2ggaXMganVzdCBhc2tpbmcgZm9yIHByb2JsZW1zLiBJZiB5b3VcbiAgICAgKiB3YW50IHRoZSBmaWxlIGRlbGV0ZWQsIGNhbGwgZGVsOyBkZWxldGlvbnMgdGFrZSB0aGVpciBvd24gcGF0aC5cbiAgICAgKi9cbiAgICBzZXQoZmlsZU5hbWU6IHN0cmluZywgZGF0YTogQnVmZmVyLCBjb25maWc/OiBTZXRDb25maWcpOiBQcm9taXNlPHN0cmluZz47XG4gICAgZGVsKGZpbGVOYW1lOiBzdHJpbmcsIGNvbmZpZz86IERlbENvbmZpZyk6IFByb21pc2U8dm9pZD47XG4gICAgLyoqIFN0cmVhbXMgYSBmaWxlIHRvbyBsYXJnZSB0byBob2xkIGluIG1lbW9yeS4gZ2V0TmV4dERhdGEgcmV0dXJucyB1bmRlZmluZWQgd2hlbiBkb25lLiBUaGlzIG9ubHkgbmVlZHMgdG8gYmUgY2FsbGVkIHdoZW4geW91IENBTk5PVCBtYXRlcmlhbGl6ZSB0aGUgZW50aXJlIGZpbGUgaW4gbWVtb3J5IC0gaWYgeW91IGNhbiwganVzdCBjYWxsIHNldDogYWJvdmUgTEFSR0VfU0VUX1RIUkVTSE9MRCBpdCBzdHJlYW1zIHRocm91Z2ggc2V0TGFyZ2VGaWxlIGludGVybmFsbHksIGtlZXBpbmcgdGhlIGNsaWVudCByZXNwb25zaXZlIGFuZCBub3Qgb3ZlcndoZWxtaW5nIHRoZSBzZXJ2ZXIuIGxhc3RNb2RpZmllZCBzdGFtcHMgdGhlIGZpbmlzaGVkIGZpbGUgbGlrZSBzZXQncyAoc3luY2hyb25pemVkIGNvcGllcyBuZWVkIGl0IHRvIGtlZXAgd3JpdGUgb3JkZXJpbmcpOyBiYWNrZW5kcyB0aGF0IHN0YW1wIHRoZWlyIG93biB0aW1lcyAoYmFja2JsYXplKSBhY2NlcHQgYW5kIGlnbm9yZSBpdC4gVEhST1dTIHdoZW4gdGhlIHN0cmVhbSBwcm9kdWNlcyBubyBkYXRhIGF0IGFsbCAtIHNhbWUgcnVsZSBhcyBzZXQ6IGFuIGVtcHR5IGZpbGUgSVMgYSBkZWxldGlvbiBhbmQgd291bGQgcmVhZCBiYWNrIGFzIG1pc3NpbmcuICovXG4gICAgc2V0TGFyZ2VGaWxlKGNvbmZpZzogeyBwYXRoOiBzdHJpbmc7IGxhc3RNb2RpZmllZD86IG51bWJlcjsgZ2V0TmV4dERhdGEoKTogUHJvbWlzZTxCdWZmZXIgfCB1bmRlZmluZWQ+IH0pOiBQcm9taXNlPHZvaWQ+O1xuICAgIC8qKiB3cml0ZVRpbWUgaXMgdGhlIGxhc3Qtd3JpdGUgdGltZSDigJQgc2VlIEFyY2hpdmVGaWxlSW5mby5jcmVhdGVUaW1lLCB3aGljaCBpcyB0aGUgc2FtZSB2YWx1ZS4gdXJsIGFzIGluIGdldDIuIFNpemUtMCBlbnRyaWVzICh0b21ic3RvbmVzKSByZXBvcnQgdW5kZWZpbmVkIHVubGVzcyBjb25maWcuaW5jbHVkZVRvbWJzdG9uZXMuICovXG4gICAgZ2V0SW5mbyhmaWxlTmFtZTogc3RyaW5nLCBjb25maWc/OiBHZXRJbmZvQ29uZmlnKTogUHJvbWlzZTx7IHdyaXRlVGltZTogbnVtYmVyOyBzaXplOiBudW1iZXI7IHVybD86IHN0cmluZyB9IHwgdW5kZWZpbmVkPjtcbiAgICAvKipcbiAgICAgKiBFbXB0eSAoc2l6ZS0wKSBmaWxlcyBhcmUgTkVWRVIgcmV0dXJuZWQgYnkgaW5kZXgtYmFja2VkIHN0b3JlcyAoQmxvYlN0b3JlLCBhbmQgdGhlcmVmb3JlIHRoZVxuICAgICAqIGNoYWluKTogYW4gZW1wdHkgZmlsZSBJUyBhIG1pc3NpbmcgZmlsZSAtIHRoZSB0b21ic3RvbmUgb2YgYSBkZWxldGlvbi4gSWYgeW91IHdhbnQgYSBtYXJrZXJcbiAgICAgKiBmaWxlIHRoYXQgc2hvd3MgdXAgaW4gbGlzdGluZ3MsIGFkZCBzb21lIGNvbnRlbnQgdG8gaXQuIFJhdyBzb3VyY2VzIChkaXNrLCBiYWNrYmxhemUpIERPIGxpc3RcbiAgICAgKiB0aGVpciBlbXB0eSBmaWxlcyAtIHRoYXQgaXMgaG93IHNjYW5zIGxlYXJuIG9mIGRlbGV0aW9ucyAtIGJ1dCBub3RoaW5nIGJ1aWx0IG9uIHRoZSBpbmRleFxuICAgICAqIGV2ZXIgc3VyZmFjZXMgdGhlbS5cbiAgICAgKi9cbiAgICBmaW5kKHByZWZpeDogc3RyaW5nLCBjb25maWc/OiBGaW5kQ29uZmlnKTogUHJvbWlzZTxzdHJpbmdbXT47XG4gICAgLyoqIFNlZSBmaW5kIGZvciB0aGUgZW1wdHktZmlsZSAodG9tYnN0b25lKSBydWxlLiAqL1xuICAgIGZpbmRJbmZvKHByZWZpeDogc3RyaW5nLCBjb25maWc/OiBGaW5kQ29uZmlnKTogUHJvbWlzZTxBcmNoaXZlRmlsZUluZm9bXT47XG4gICAgLyoqIE9ubHkgd29ya3MgZm9yIHB1YmxpYyBidWNrZXRzIChwcml2YXRlIGJ1Y2tldHMgYXJlIEFQSS1hY2Nlc3Mgb25seSkuICovXG4gICAgZ2V0VVJMKHBhdGg6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPjtcbiAgICAvKiogVGhlIGJ1Y2tldCdzIGNvbmZpZ3VyYXRpb24sIHdoaWNoIHRlbGxzIHdoZXRoZXIgdGhlIG9wdGlvbmFsIGZ1bmN0aW9ucyBhcmUgc3VwcG9ydGVkLiAqL1xuICAgIGdldENvbmZpZygpOiBQcm9taXNlPEFyY2hpdmVzQ29uZmlnPjtcbiAgICAvKipcbiAgICAgKiBBbGwgZmlsZXMgY2hhbmdlZCBhZnRlciBjb25maWcudGltZSwgb3B0aW9uYWxseSByZXN0cmljdGVkIHRvIGtleXMgcm91dGluZyBpbnRvIG9uZSBvZlxuICAgICAqIGNvbmZpZy5yb3V0ZXMgKHVzZWQgYnkgc2Nhbm5pbmcsIHNvIHBhcnRpYWxseS1vdmVybGFwcGluZyBzaGFyZHMgb25seSByZWNlaXZlIHRoZWlyIHNsaWNlKS5cbiAgICAgKiBXaGVuIGdldENvbmZpZygpLnN1cHBvcnRzQ2hhbmdlc0FmdGVyLCB0aGlzIGlzIGJhY2tlZCBieSBhbiBpbmRleCAoZmFzdCwgYW5kIGRlbGV0aW9ucyBBUkVcbiAgICAgKiByZXBvcnRlZCwgYXMgc2l6ZS0wIHRvbWJzdG9uZSBlbnRyaWVzKS4gRXZlcnkgb3RoZXIgYmFja2VuZCBlbXVsYXRlcyBpdDogYSBmdWxsIGZpbmRJbmZvXG4gICAgICogbGlzdGluZyBmaWx0ZXJlZCBpbiBtZW1vcnkgLSBjb3JyZWN0LCBidXQgbm8gY2hlYXBlciB0aGFuIHRoZSBsaXN0aW5nIGl0c2VsZi5cbiAgICAgKi9cbiAgICBnZXRDaGFuZ2VzQWZ0ZXIyKGNvbmZpZzogQ2hhbmdlc0FmdGVyQ29uZmlnKTogUHJvbWlzZTxBcmNoaXZlRmlsZUluZm9bXT47XG4gICAgLyoqIFN5bmNocm9uaXphdGlvbiBpbnRyb3NwZWN0aW9uLCBmb3IgYmFja2VuZHMgdGhhdCBzeW5jaHJvbml6ZSBmcm9tIHNvdXJjZXMgKHNlZSBCbG9iU3RvcmUpLiAqL1xuICAgIGdldFN5bmNTdGF0dXM/KCk6IFByb21pc2U8QXJjaGl2ZXNTeW5jU3RhdHVzPjtcbn1cbiJdfQ==
91
- /* _JS_SOURCE_HASH = "e5bbbfd03c168063bd0a9d862497c952601efba69725a28afdb27dca9e225348"; */
95
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiSUFyY2hpdmVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiSUFyY2hpdmVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSx3S0FBd0s7OztBQUV4SyxzSkFBc0o7QUFDekksUUFBQSx3QkFBd0IsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQUV2RCx5TEFBeUw7QUFDNUssUUFBQSxvQkFBb0IsR0FBRyxLQUFLLEdBQUcsSUFBSSxDQUFDO0FBQ2pELFNBQWdCLHVCQUF1QixDQUFDLFlBQW9CO0lBQ3hELElBQUksR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxnQ0FBd0IsQ0FBQztJQUNoRCxJQUFJLFlBQVksR0FBRyxHQUFHLEVBQUUsQ0FBQztRQUNyQixNQUFNLElBQUksS0FBSyxDQUFDLDBDQUEwQyxZQUFZLE1BQU0sR0FBRyxxQkFBcUIsQ0FBQyxDQUFDO0lBQzFHLENBQUM7QUFDTCxDQUFDO0FBTEQsMERBS0M7QUEwRVksUUFBQSxpQkFBaUIsR0FBcUIsQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUM7QUEyR2hGLHdYQUF3WDtBQUMzVyxRQUFBLDBCQUEwQixHQUFHLDRDQUE0QyxDQUFDO0FBRXZGLDhMQUE4TDtBQUNqTCxRQUFBLG1CQUFtQixHQUFHLHFDQUFxQyxDQUFDO0FBRTVELFFBQUEsVUFBVSxHQUFxQixDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUVuRCwyUkFBMlI7QUFDOVEsUUFBQSxjQUFjLEdBQUcsNkNBQTZDLENBQUM7QUFDNUUsb0xBQW9MO0FBQ3BMLDhKQUE4SjtBQUM5SixTQUFnQixtQkFBbUIsQ0FBQyxXQUF5QztJQUN6RSxJQUFJLENBQUMsV0FBVztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQzlCLE9BQU8sV0FBVyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztBQUN2QyxDQUFDO0FBSEQsa0RBR0M7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SUFBSTtRQUNKLFlBQVksRUFBRSxjQUFjO1FBQzVCLFdBQVcsRUFBRSxLQUFLLElBQUksRUFBRTtZQUNwQixJQUFJLE1BQU0sSUFBSSxTQUFTO2dCQUFFLE9BQU8sU0FBUyxDQUFDO1lBQzFDLElBQUksR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxHQUFHLGdCQUFnQixFQUFFLFNBQVMsQ0FBQyxDQUFDO1lBQ3pELElBQUksSUFBSSxHQUFHLE1BQU0sSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsRUFBRSxLQUFLLEVBQUUsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxFQUFFLFFBQVEsRUFBRSxNQUFNLENBQUMsUUFBUSxFQUFFLFdBQVcsRUFBRSxNQUFNLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztZQUMvSCxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUN4QixNQUFNLElBQUksS0FBSyxDQUFDLGtCQUFrQixJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxTQUFTLElBQUksQ0FBQyxZQUFZLEVBQUUsYUFBYSxJQUFJLElBQUksSUFBSSxDQUFDLE1BQU0sSUFBSSxTQUFTLE9BQU8sTUFBTSxJQUFJLEdBQUcsY0FBYyxHQUFHLEdBQUcsTUFBTSxlQUFlLFNBQVMsK0NBQStDLENBQUMsQ0FBQztZQUMxUCxDQUFDO1lBQ0QsTUFBTSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUM7WUFDdEIsT0FBTyxJQUFJLENBQUM7UUFDaEIsQ0FBQztLQUNKLENBQUMsQ0FBQztJQUNILE9BQU8sRUFBRSxTQUFTLEVBQUUsY0FBYyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsQ0FBQztBQUMxRCxDQUFDO0FBOUNELDBDQThDQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIFRoZSBpbXBvcnRhbnQgb3BlcmF0aW9ucyBvZiBhbiBhcmNoaXZlIGJ1Y2tldCAoZXh0cmFjdGVkIGZyb20gQXJjaGl2ZXNCYWNrYmxhemUpLCBzbyBvdGhlciBiYWNrZW5kcyAoZS5nLiBvdXIgb3duIHJlbW90ZSBzdG9yYWdlIHNlcnZlcikgY2FuIGJlIHVzZWQgaW50ZXJjaGFuZ2VhYmx5LlxuXG4vLyBBIHdyaXRlIG1heSBub3QgYmUgc3RhbXBlZCBtb3JlIHRoYW4gdGhpcyBmYXIgaW4gdGhlIGZ1dHVyZSwgb3IgY2xvY2sgc2tldyBiZXR3ZWVuIG1hY2hpbmVzIHdvdWxkIGxldCBhIGJhZCB0aW1lc3RhbXAgYmxvY2sgd3JpdGVzIGZvciBhIGxvbmcgdGltZS5cbmV4cG9ydCBjb25zdCBNQVhfTEFTVF9NT0RJRklFRF9GVVRVUkUgPSAxNSAqIDYwICogMTAwMDtcblxuLy8gSG93IGxvbmcgYnJvd3NlcnMgbWF5IGNhY2hlIGZpbGVzIGZyb20gaW1tdXRhYmxlIGJ1Y2tldHMgKHRoZSBDYWNoZS1Db250cm9sIG1heC1hZ2UpLCBzaGFyZWQgYnkgZXZlcnkgaG9zdGluZyBwYXRoIChiYWNrYmxhemUgYnVja2V0IHNldHRpbmdzIGFuZCBvdXIgb3duIHN0b3JhZ2Ugc2VydmVyJ3MgSFRUUCByb3V0ZSlcbmV4cG9ydCBjb25zdCBJTU1VVEFCTEVfQ0FDSEVfVElNRSA9IDg2NDAwICogMTAwMDtcbmV4cG9ydCBmdW5jdGlvbiBhc3NlcnRWYWxpZExhc3RNb2RpZmllZChsYXN0TW9kaWZpZWQ6IG51bWJlcik6IHZvaWQge1xuICAgIGxldCBtYXggPSBEYXRlLm5vdygpICsgTUFYX0xBU1RfTU9ESUZJRURfRlVUVVJFO1xuICAgIGlmIChsYXN0TW9kaWZpZWQgPiBtYXgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBsYXN0TW9kaWZpZWQgaXMgdG9vIGZhciBpbiB0aGUgZnV0dXJlOiAke2xhc3RNb2RpZmllZH0gPiAke21heH0gKG5vdyArIDE1IG1pbnV0ZXMpYCk7XG4gICAgfVxufVxuXG5cbmV4cG9ydCB0eXBlIFJlbW90ZUNvbmZpZyA9IHtcbiAgICAvLyBOT1RFOiBWZXJzaW9uIGlzIHVzZWQgd2hlbiB1cGRhdGluZyB0aGUgY29uZmlndXJhdGlvbi4gVGhlIG5ld2VyIHZlcnNpb24gaXMgYWx3YXlzIHRha2VuLiBBIG1pc3NpbmcgdmVyc2lvbiBjb3VudHMgYXMgdmVyc2lvbiAtMS5cbiAgICB2ZXJzaW9uPzogbnVtYmVyO1xuICAgIHNvdXJjZXM6IFJlbW90ZUNvbmZpZ0Jhc2VbXTtcbn07XG5cbi8qKlxuICAgIHN0cmluZyBhcmd1bWVudHMgd2lsbCBiZSBhIHVybCwgbG9va2luZyBsaWtlOlxuICAgICAgICBodHRwczovL3N0b3JhZ2UyLnZpZGdyaWR3ZWIuY29tOjQ0NDUvZmlsZS9leGFtcGxlYWNjb3VudC9leGFtcGxlYnVja2V0L3N0b3JhZ2Uvc3RvcmFnZXJvdXRpbmcuanNvblxuICAgICAgICBodHRwczovL2YwMDIuYmFja2JsYXplYjIuY29tL2ZpbGUvcXVlcnlzdWJ0ZXN0LWNvbS1wdWJsaWMtaW1tdXRhYmxlL3N0b3JhZ2Uvc3RvcmFnZXJvdXRpbmcuanNvblxuICAgICAgICAtIFRoZXNlIG1hcCB0byB7IHVybCB9LCB3aXRoIHRoZSB0eXBlIGluZmVycmVkIGZyb20gdGhlIHVybFxuICAgICAgICAtIEhvc3RlZCB1cmxzIGFyZSAvZmlsZS88YWNjb3VudD4vPGJ1Y2tldE5hbWU+Ly4uLiwgYmFja2JsYXplIHVybHMgYXJlIC9maWxlLzxidWNrZXROYW1lPi8uLi5cblxuICAgIE5PVEU6IElmIHdlIGRvIG5vdCBoYXZlIHJpZ2h0IGFjY2VzcyB0byB0aGVzZSwgdGhlbiBpdCBiZWNvbWVzIGEgcmVhZC1vbmx5IElBcmNoaXZlcywgd2hlcmUgd2Ugc29sZWx5IHJlYWQgdXNpbmcgdGhlIHVybCBmb3JtICh3aGljaCBtaWdodCB0aHJvdyBkdWUgdG8gbm90IGhhdmluZyBhY2Nlc3MgYXMgd2VsbCkuIFVOTEVTUyBPdXIgY29uZmlndXJhdGlvbiBleHBsaWNpdGx5IGhhcyBwdWJsaWM6IGZhbHNlLCBpbiB3aGljaCBjYXNlLCB3ZSBkb24ndCBldmVuIGhpdCB0aGUgVVJMIGFuZCB3ZSB0aHJvdyBvbiBhY2Nlc3MuXG5cbiAgICBOT1RFOiBJZiB3ZSdyZSBpbiB0aGUgYnJvd3Nlciwgd2Ugc2hvdWxkIGFsbG93IGRvd25sb2FkaW5nIHRoZSBmaWxlcyB2aWEgdGhlIFVSTCBmb3JtIChpZiBpdCdzIGEgcHVibGljIGJ1Y2tldCksIGhvd2V2ZXIsIHdlIHdvbid0IGFsbG93IHdyaXRpbmcsIGJlY2F1c2UgdGhlaXIgc2VydmVycyBkbyBub3QgYWxsb3cgc2VjdXJlIGJyb3dzZXIgd3JpdGVzLlxuKi9cbmV4cG9ydCB0eXBlIFJlbW90ZUNvbmZpZ0Jhc2UgPSBzdHJpbmcgfCBTb3VyY2VDb25maWc7XG5cbi8qKiBPbmUgY29uZmlndXJlZCBzb3VyY2UgaW4gYSByb3V0aW5nIGNvbmZpZzogYSBob3N0ZWQgKG91ciBzdG9yYWdlIHNlcnZlcikgb3IgYmFja2JsYXplIGVudHJ5LiBSZXF1ZXN0cyBjYXJyeSB0aGUgZXhhY3QgU291cmNlQ29uZmlnIHRoZXkgc2VsZWN0ZWQsIGFuZCB0aGUgc2VydmVyIG1hdGNoZXMgaXQgYWdhaW5zdCBpdHMgb3duIGVudHJpZXMgdG8gcGljayB0aGUgYmFja2luZyBzdG9yZS4gKi9cbmV4cG9ydCB0eXBlIFNvdXJjZUNvbmZpZyA9IEhvc3RlZENvbmZpZyB8IEJhY2tibGF6ZUNvbmZpZztcblxuZXhwb3J0IHR5cGUgQ29tbW9uQ29uZmlnID0ge1xuICAgIC8qKiBCeSBkZWZhdWx0IGEgc2VydmVyIGhvc3RpbmcgdGhpcyBidWNrZXQgZWFnZXJseSBjb3BpZXMgdGhpcyBzb3VyY2UncyBmdWxsIGNvbnRlbnRzIG9udG8gaXRzIG93biBkaXNrIChvbiB0b3Agb2YgdGhlIGxhenkgcmVhZC10aHJvdWdoIGNhY2hpbmcpLiBTZXQgdGhpcyB0byBiZSBhIGZyb250IGVuZCBmb3IgYSB2ZXJ5IGxhcmdlIGRhdGFiYXNlIHdpdGhvdXQgY29weWluZyB0aGUgZnVsbCBkYXRhYmFzZSAtIHJlYWRzIHN0aWxsIGRvd24tY2FjaGUgaW5kaXZpZHVhbCBmaWxlcyBvbiBkZW1hbmQuICovXG4gICAgbm9GdWxsU3luYz86IGJvb2xlYW47XG4gICAgLyoqIEJ5dGVzIG9mIHJlYWQtY2FjaGUgdGhpcyBzZXJ2ZXIncyBkaXNrIG1heSBob2xkOyBsZWFzdC1yZWNlbnRseS11c2VkIGZpbGVzIGFyZSBkZWxldGVkIGZyb20gZGlzayB0byBzdGF5IHVuZGVyIGl0IChvbmx5IGV2ZXIgd2hlbiBhbm90aGVyIHNvdXJjZSB2ZXJpZmlhYmx5IGhvbGRzIHRoZSBmaWxlIC0gdGhlIG9ubHkgY29weSBpcyBuZXZlciBkZWxldGVkKS4gUmVxdWlyZXMgbm9GdWxsU3luYyAoYSBmdWxsIGNvcHkgY2FuJ3QgYmUgYm91bmRlZCkuICovXG4gICAgcmVhZGVyRGlza0xpbWl0PzogbnVtYmVyO1xuICAgIC8qKiBUaGUgd3JpdGUgdGltZXMgKFtzdGFydE1zLCBlbmRNc10pIHRoaXMgc291cmNlIGlzIHZhbGlkIGZvciAoc2VlIEFyY2hpdmVzU291cmNlLnZhbGlkV2luZG93IGZvciB0aGUgc3luY2hyb25pemF0aW9uIHNlbWFudGljcykuIFJlcXVpcmVkIG9uIG9iamVjdCBjb25maWdzOiBjb25maWd1cmF0aW9uIGNoYW5nZXMgbXVzdCBiZSBTQ0hFRFVMRUQgKGEgbmV3IHNvdXJjZSBiZWNvbWVzIHZhbGlkIGF0IGEgZnV0dXJlIHRpbWUgd2hpbGUgdGhlIG9sZCBvbmUncyB3aW5kb3cgZW5kcyksIG5vdCBmbGlwcGVkIGluc3RhbnRseS4gUGxhaW4gVVJMLXN0cmluZyBzb3VyY2VzIGRlZmF1bHQgdG8gRlVMTF9WQUxJRF9XSU5ET1cgLSBvbmNlIHlvdSdyZSB3cml0aW5nIG9iamVjdCBjb25maWdzLCB5b3UncmUgZG9pbmcgc29tZXRoaW5nIGNvbXBsaWNhdGVkIGVub3VnaCB0byB0aGluayBhYm91dCB3aGVuIHRoaW5ncyBjaGFuZ2UuICovXG4gICAgdmFsaWRXaW5kb3c6IFtudW1iZXIsIG51bWJlcl07XG4gICAgLyoqIFNoYXJkaW5nOiB0aGUgZnJhY3Rpb24gb2YgdGhlIGtleSBzcGFjZSB0aGlzIHNvdXJjZSBoYW5kbGVzLCBhcyBbc3RhcnQsIGVuZCkgb3ZlciBbMCwgMSkgKGtleXMgYXJlIHJvdXRlZCBieSBnZXRSb3V0ZSBpbiByZW1vdGVDb25maWcudHMpLiBEZWZhdWx0cyB0byBGVUxMX1JPVVRFICh1bnNoYXJkZWQpLiBBdCBldmVyeSBwb2ludCBpbiB0aW1lIHRoZSBzb3VyY2VzJyByb3V0ZXMgbXVzdCBmdWxseSBjb3ZlciBbMCwgMSksIG9yIHNvbWUga2V5cyBjb3VsZCBuZXZlciBiZSByZWFkLiAqL1xuICAgIHJvdXRlPzogW251bWJlciwgbnVtYmVyXTtcbiAgICAvKiogU2V0IG9uIGVudHJpZXMgaW5qZWN0ZWQgaW50byB0aGUgaW4tbWVtb3J5IGNvbmZpZyBieSBhbiBvdmVybGF5IChhIGRlcGxveSBzd2l0Y2hvdmVyJ3MgYWx0ZXJuYXRlLXBvcnQgd2luZG93KS4gTmV2ZXIgd3JpdHRlbiB0byBkaXNrOiByZXNvbHZlSW50ZXJtZWRpYXRlU291cmNlcyBzdHJpcHMgdGhlc2UgYW5kIHJlam9pbnMgdGhlIHdpbmRvd3MgYXJvdW5kIHRoZW0sIHdoaWNoIGlzIGFsc28gaG93IGEgY2xpZW50IHRlbGxzIHdoZXRoZXIgYW4gdXBkYXRlIGlzIGEgcmVhbCBjb25maWd1cmF0aW9uIGNoYW5nZSBvciBqdXN0IGFuIG92ZXJsYXkuICovXG4gICAgaW50ZXJtZWRpYXRlPzogYm9vbGVhbjtcbn07XG5cbmV4cG9ydCB0eXBlIEhvc3RlZENvbmZpZyA9IENvbW1vbkNvbmZpZyAmIHtcbiAgICB0eXBlOiBcInJlbW90ZVwiO1xuXG4gICAgLy8gRXg6IGh0dHBzOi8vOTktMjUwLTEyNC05MS5xdWVyeXN1YnRlc3QuY29tOjUyMzMvZmlsZS9yb290L3VuaXF1ZWJ1Y2tldG5hbWUvc3RvcmFnZS9zdG9yYWdlcm91dGluZy5qc29uXG4gICAgLy8gTk9URTogVGhlIGFjY291bnQgYW5kIGJ1Y2tldCBuYW1lIGFyZSBvYnRhaW5lZCBmcm9tIHRoZSBVUkwuXG4gICAgdXJsOiBzdHJpbmc7XG5cbiAgICAvLyBOT1RFOiBBdXRoZW50aWNhdGlvbiBpcyBoYW5kbGVkIGJ5IGNlcnQudHMsIHZpYSBoYXZpbmcgeW91ciBtYWNoaW5lIHRydXN0ZWQgdG8gYWNjZXNzIHRoaXMgYWNjb3VudC4gXG5cbiAgICBwdWJsaWM/OiBib29sZWFuO1xuICAgIC8vIEZhc3QgbW9kZTogdGhlIHNlcnZlciBhY2tub3dsZWRnZXMgd3JpdGVzIG9uY2UgdGhleSBhcmUgaW4gbWVtb3J5LCBmbHVzaGluZyB0byBkaXNrIGFmdGVyIHdyaXRlRGVsYXkgKGRlZmF1bHQgNSBtaW51dGVzKSBhbmQgY29hbGVzY2luZyB3cml0ZXMgdG8gdGhlIHNhbWUgZmlsZS4gQSBzZXJ2ZXIgY3Jhc2ggbG9zZXMgd3JpdGVzIHRoYXQgaGF2ZW4ndCBmbHVzaGVkIHlldC5cbiAgICBmYXN0PzogYm9vbGVhbjtcbiAgICB3cml0ZURlbGF5PzogbnVtYmVyO1xuICAgIC8vIFRoZSBidWNrZXQgaXMgc2VydmVkIHN0cmFpZ2h0IGZyb20gdGhlIHNlcnZlcidzIGRpc2ssIHdpdGggbm8gaW5kZXgg4oCUIHNvIG5vIGZhc3Qgd3JpdGVzLCBubyBnZXRTeW5jU3RhdHVzLCBhbmQgZ2V0Q2hhbmdlc0FmdGVyMiBmYWxscyBiYWNrIHRvIGEgZnVsbCBsaXN0aW5nLlxuICAgIHJhd0Rpc2s/OiBib29sZWFuO1xuICAgIC8vIFdyaXRlcyB0byBwYXRocyB0aGF0IGFscmVhZHkgZXhpc3QgYXJlIGRpc2FsbG93ZWQgKGRlbGV0ZXMgc3RpbGwgd29yaykuXG4gICAgaW1tdXRhYmxlPzogYm9vbGVhbjtcbn07XG5cbmV4cG9ydCB0eXBlIEJhY2tibGF6ZUNvbmZpZyA9IENvbW1vbkNvbmZpZyAmIHtcbiAgICB0eXBlOiBcImJhY2tibGF6ZVwiO1xuICAgIC8vIEV4OiBodHRwczovL2YwMDIuYmFja2JsYXplYjIuY29tL2ZpbGUvcXVlcnlzdWJ0ZXN0LWNvbS1wdWJsaWMtaW1tdXRhYmxlL3N0b3JhZ2Uvc3RvcmFnZXJvdXRpbmcuanNvblxuICAgIC8vIE5PVEU6IFRoZSBidWNrZXQgbmFtZSBpcyBvYnRhaW5lZCBmcm9tIHRoZSBVUkwuXG4gICAgdXJsOiBzdHJpbmc7XG4gICAgLy8gUHVibGljIGJ1Y2tldHMgYXJlIHNlcnZlZCBvdmVyIHBsYWluIEhUVFBTIEdFVHMgKGdldFVSTCkuIFByaXZhdGUgYnVja2V0cyBhcmUgQVBJLWFjY2VzcyBvbmx5LlxuICAgIHB1YmxpYz86IGJvb2xlYW47XG4gICAgLy8gTk9URTogVGhpcyBpc24ndCBlbmZvcmNlZCBvbiB0aGUgYmFja2JsYXplIGxldmVsLCBzbyB0aGlzIGlzIGp1c3QgYSBjbGllbnQtc2lkZSBndWFyYW50ZWUuIFRoaXMgY2FuIGNoYW5nZSBob3cgd2UgY2FjaGUgZmlsZXMuXG4gICAgLy8gIC0gQmFja2JsYXplIGRvZXMgc3VwcG9ydCBpbW11dGFiaWxpdHkuIEhvd2V2ZXIsIGFwcGFyZW50bHksIG9uY2Ugd2UgZW5hYmxlIGl0IG9uIGEgYnVja2V0LCB3ZSBjYW4ndCBkaXNhYmxlIGl0LCB3aGljaCBpcyByZWFsbHkgYmFkLCBhcyBpdCBtZWFucyBpZiBvdXIgY29kZSBjb3VsZCBldmVyIGVuYWJsZSBpdCBhbmQgd2UgYWNjaWRlbnRhbGx5IGVuYWJsZSBpdCBvbiBhbiBpbXBvcnRhbnQgYnVja2V0LCB3ZSBlc3NlbnRpYWxseSBqdXN0IGJyaWNrZWQgdGhhdCBidWNrZXQuIFNvIHdlIHNob3VsZCBuZXZlciB3cml0ZSBhbnkgY29kZSB0aGF0IGV2ZXIgdHJpZXMgdG8gdXNlIGJhY2tibGF6ZSB0byBtYWtlIHRoaW5ncyBpbW11dGFibGUuIFxuICAgIGltbXV0YWJsZT86IGJvb2xlYW47XG4gICAgLy8gQ09SUyBvcmlnaW5zIGFsbG93ZWQgdG8gY29uc3VtZSB0aGUgYnVja2V0J3MgZmlsZXMgaW4gYSBicm93c2VyLiBOb3QgYSBzZWN1cml0eSBib3VuZGFyeSAoYWNjZXNzIGlzIGdhdGVkIGJ5IHRoZSBBUEkga2V5IC8gc2lnbmVkIFVSTHMsIG5laXRoZXIgb2Ygd2hpY2ggcmlkZXMgaW4gY29va2llcykgLSBpdCBvbmx5IGNvbnRyb2xzIHdoaWNoIHNpdGVzJyBpbi1wYWdlIEphdmFTY3JpcHQgY2FuIHJlYWQgcmVzcG9uc2VzLiBEZWZhdWx0cyB0byBhbnkgSFRUUFMgb3JpZ2luLlxuICAgIGFsbG93ZWRPcmlnaW5zPzogc3RyaW5nW107XG5cbiAgICAvLyBOT1RFOiBXZSB3aWxsIGFjY2VzcyB0aGUgYXBpIGtleSBmcm9tIGdldFNlY3JldCwgc2VlIGJhY2tibGF6ZS50cyBmb3IgdGhlIHNwZWNpZmljIGtleXMuXG59O1xuXG5cbmV4cG9ydCBjb25zdCBGVUxMX1ZBTElEX1dJTkRPVzogW251bWJlciwgbnVtYmVyXSA9IFswLCBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUl07XG5cblxuXG5cbmV4cG9ydCB0eXBlIEdldENvbmZpZyA9IHtcbiAgICByYW5nZT86IHsgc3RhcnQ6IG51bWJlcjsgZW5kOiBudW1iZXIgfTtcbiAgICAvKiogUmVhZCBPTkxZIGZyb20gdGhlIHByaW1hcnkgc291cmNlIC0gdGhlIG9uZSB3cml0ZXMgd291bGQgdGFyZ2V0IC0gaW5zdGVhZCBvZiBmYWxsaW5nIGJhY2sgYWNyb3NzIHRoZSByZWR1bmRhbnQgc291cmNlcy4gVXNlIHRoaXMgd2hlbiB5b3Ugd2FudCB5b3VyIHJlYWRzIGFuZCB3cml0ZXMgdG8gYmUgc29tZXdoYXQgYXRvbWljOiB0aGVyZSB3aWxsIHN0aWxsIGJlIGlzc3VlcyB3aXRoIHRoZSByb3VuZCB0cmlwLCBidXQgd2l0aG91dCBpdCB5b3UgY291bGQgdGFsayB0byBhIGNvbXBsZXRlbHkgZGlmZmVyZW50IG5vZGUgYW5kIGdldCBhIG11Y2ggb2xkZXIgdmFsdWUuIE1vc3QgcmVhZHMgYXJlbid0IGZvbGxvd2VkIGJ5IGEgd3JpdGUgdGhvdWdoLCBzbyBmb3IgbW9zdCBjYXNlcyBpdCdzIGJldHRlciB0byBnZXQgYSB2YWx1ZSB0aGFuIHRvIGhhdmUgdG8gd2FpdCAob3IgZXZlbiB0aHJvdykgd2hlbiB0aGUgcHJpbWFyeSBub2RlIGlzIG5vdCBhdmFpbGFibGUuICovXG4gICAgbm9GYWxsYmFja3M/OiBib29sZWFuO1xuICAgIC8qKiBTdG9yZS10by1zdG9yZSBjYWxsOiB0aGUgc2VydmluZyBub2RlIGFuc3dlcnMgcHVyZWx5IGZyb20gaXRzIG93biBkaXNrLCBjb21wbGV0ZWx5IHNob3J0LWNpcmN1aXRpbmcgaXRzIGluZGV4IGhvbGRlcnMgLSBjaGFzaW5nIGl0cyBvd24gcmVtb3RlIGhvbGRlcnMgd2hpbGUgYW5zd2VyaW5nIGFub3RoZXIgc3RvcmUgaXMgaG93IGluZmluaXRlIGdldCBsb29wcyBiZXR3ZWVuIHN0b3JlcyBmb3JtIChBIGFza3MgQiwgQidzIGluZGV4IHBvaW50cyBiYWNrIGF0IEEsIC4uLikuIE5vIHdpbmRvdyBvciByb3V0ZSBjaGVja3Mgb24gcmVhZHM6IGlmIHRoZSBieXRlcyBhcmUgb24gaXRzIGRpc2ssIHRoZSBjYWxsZXIgbWF5IGhhdmUgdGhlbS4gKi9cbiAgICBpbnRlcm5hbD86IGJvb2xlYW47XG4gICAgLyoqIEFsc28gcmV0dXJuIHNpemUtMCByZXN1bHRzICh0b21ic3RvbmVzIC0gYW4gZW1wdHkgZmlsZSBJUyBhIG1pc3NpbmcgZmlsZSkgaW5zdGVhZCBvZiB0cmVhdGluZyB0aGVtIGFzIGFic2VudC4gT2ZmIGJ5IGRlZmF1bHQsIG1hdGNoaW5nIGdldEluZm8ncyBmbGFnIG9mIHRoZSBzYW1lIG5hbWUuIFN5bmNocm9uaXphdGlvbiBwYXNzZXMgdGhpcyBzbyBhIERFTEVURUQgZmlsZSAod2l0aCBpdHMgd3JpdGUgdGltZSkgaXMgZGlzdGluZ3Vpc2hhYmxlIGZyb20gYSBmaWxlIHRoYXQgbmV2ZXIgZXhpc3RlZC4gKi9cbiAgICBpbmNsdWRlVG9tYnN0b25lcz86IGJvb2xlYW47XG59O1xuXG5leHBvcnQgdHlwZSBGaW5kQ29uZmlnID0ge1xuICAgIHNoYWxsb3c/OiBib29sZWFuO1xuICAgIHR5cGU/OiBcImZpbGVzXCIgfCBcImZvbGRlcnNcIjtcbiAgICAvKiogTGlzdGluZ3Mgbm9ybWFsbHkgY29tZSBPTkxZIGZyb20gdGhlIGF1dGhvcml0YXRpdmUgc291cmNlcyAodGhlIHNhbWUgbm9kZXMgd3JpdGVzIGdvIHRvIC0gcmVhZC15b3VyLXdyaXRlcykuIFdpdGggZmFsbGJhY2tzLCBhIGZhaWxpbmcgc2hhcmQncyByb3V0ZXMgYXJlIGNvdmVyZWQgYnkgdGhlIG5leHQgc291cmNlIGhvbGRpbmcgdGhlbSAoZS5nLiBhIHdpZGUgcmVhZCByZXBsaWNhKSBpbnN0ZWFkIG9mIHRoZSBjYWxsIGZhaWxpbmcgLSBoaWdoIGF2YWlsYWJpbGl0eSBhdCB0aGUgY29zdCBvZiBwb3NzaWJseSBtaXNzaW5nIGp1c3Qtd3JpdHRlbiBkYXRhLiBTaW5nbGUtc291cmNlIGFyY2hpdmVzIGlnbm9yZSB0aGUgZmxhZy4gKi9cbiAgICBmYWxsYmFja3M/OiBib29sZWFuO1xufTtcblxuZXhwb3J0IHR5cGUgRGVsQ29uZmlnID0ge1xuICAgIC8qKiBTdGFtcHMgdGhlIGRlbGV0aW9uIChpdHMgdG9tYnN0b25lKSB3aXRoIHRoaXMgd3JpdGUgdGltZSBpbnN0ZWFkIG9mIG5vdy4gU3luY2hyb25pemF0aW9uIHBhc3NlcyB0aGUgT1JJR0lOQUwgZGVsZXRpb24gdGltZSwgc28gZGVsZXRpb24gb3JkZXJpbmcgc3Vydml2ZXMgcHJvcGFnYXRpb24gZXhhY3RseSBsaWtlIGFueSBvdGhlciB3cml0ZSdzIG9yZGVyaW5nLiAqL1xuICAgIGxhc3RNb2RpZmllZD86IG51bWJlcjtcbiAgICAvKiogU2VlIFNldENvbmZpZy5pbnRlcm5hbC4gKi9cbiAgICBpbnRlcm5hbD86IGJvb2xlYW47XG4gICAgLyoqIFNlZSBTZXRDb25maWcubm9DaGVja3MuICovXG4gICAgbm9DaGVja3M/OiBib29sZWFuO1xuICAgIC8qKiBTZWUgU2V0Q29uZmlnLmZhbGxiYWNrcy4gKi9cbiAgICBmYWxsYmFja3M/OiBib29sZWFuO1xufTtcblxuZXhwb3J0IHR5cGUgR2V0SW5mb0NvbmZpZyA9IHtcbiAgICAvKiogQWxzbyByZXBvcnQgc2l6ZS0wIGVudHJpZXMgKHRvbWJzdG9uZXMgLSBhbiBlbXB0eSBmaWxlIElTIGEgbWlzc2luZyBmaWxlKS4gT2ZmIGJ5IGRlZmF1bHQsIHNvIGEgZGVsZXRlZCBrZXkgcmVwb3J0cyB1bmRlZmluZWQsIG1hdGNoaW5nIGdldC4gU3luY2hyb25pemF0aW9uLXN0eWxlIGNhbGxlcnMgcGFzcyB0aGlzIHdoZW4gdGhleSBuZWVkIGEgZGVsZXRpb24ncyB3cml0ZSB0aW1lIChlLmcuIHRvIGNvbXBhcmUgaXQgYWdhaW5zdCBhIHdyaXRlIHRoZXkgYXJlIGFib3V0IHRvIG1ha2UpLiAqL1xuICAgIGluY2x1ZGVUb21ic3RvbmVzPzogYm9vbGVhbjtcbiAgICAvKiogU2VlIEdldENvbmZpZy5ub0ZhbGxiYWNrczogYW5zd2VyIE9OTFkgZnJvbSB0aGUgcHJpbWFyeSBzb3VyY2UgKHRoZSBvbmUgd3JpdGVzIHdvdWxkIHRhcmdldCkgaW5zdGVhZCBvZiBmYWxsaW5nIGJhY2sgYWNyb3NzIHRoZSByZWR1bmRhbnQgc291cmNlcy4gKi9cbiAgICBub0ZhbGxiYWNrcz86IGJvb2xlYW47XG59O1xuXG5leHBvcnQgdHlwZSBDaGFuZ2VzQWZ0ZXJDb25maWcgPSB7XG4gICAgdGltZTogbnVtYmVyO1xuICAgIC8qKiBPbmx5IGtleXMgcm91dGluZyBpbnRvIG9uZSBvZiB0aGVzZSBbc3RhcnQsIGVuZCkgcmFuZ2VzLiBPbmx5IHNjYW5uaW5nIHBhc3NlcyB0aGlzIC0gaXQgbGV0cyBhIHN0b3JlIHN5bmNpbmcgYSBwYXJ0aWFsIHNoYXJkIGFzayBmb3IganVzdCBpdHMgc2xpY2UuICovXG4gICAgcm91dGVzPzogW251bWJlciwgbnVtYmVyXVtdO1xufTtcblxuZXhwb3J0IHR5cGUgU2V0Q29uZmlnID0ge1xuICAgIGxhc3RNb2RpZmllZD86IG51bWJlcjtcbiAgICAvKiogTWFrZXMgdGhlIHdyaXRlIGFjY2VwdGFibGUgb24gaW1tdXRhYmxlIHRhcmdldHM6IGFuIGV4aXN0aW5nIHBhdGggaXMgc2ltcGx5IGtlcHQgKGltbXV0YWJpbGl0eSB3aW5zIC0gbm90aGluZyBpcyBvdmVyd3JpdHRlbikgaW5zdGVhZCBvZiB0aGUgd3JpdGUgdGhyb3dpbmcuIFJlcXVpcmVzIGxhc3RNb2RpZmllZC4gU3luY2hyb25pemF0aW9uIE1VU1QgcGFzcyB0aGlzIG9uIGV2ZXJ5IHB1c2ggLSBhIHBsYWluIHNldCB0aHJvd3Mgb24gaW1tdXRhYmxlIHRhcmdldHMsIHdoaWNoIHdvdWxkIGFib3J0IHJlY29uY2lsaWF0aW9uIHdoZW5ldmVyIG9uZSBzb3VyY2UgaW4gYSBjaGFpbiBpcyBpbW11dGFibGUuICovXG4gICAgZm9yY2VTZXRJbW11dGFibGU/OiBib29sZWFuO1xuICAgIC8qKiBTa2lwcyBSRURVTkRBTlQgdGFyZ2V0LXNpZGUgc2FmZXR5IHJlYWRzIGFyb3VuZCB0aGUgd3JpdGUgKGJhY2tibGF6ZTogdGhlIHBvc3QtdXBsb2FkIGV4aXN0ZW5jZSBwb2xsKS4gSXQgZG9lcyBOT1Qgc2tpcCBjaGVja3MgdGhhdCBhcmUgdGhlIHRhcmdldCdzIG9ubHkgb3JkZXJpbmcgZ3VhcmQ6IGJhY2tibGF6ZSdzIHByZS13cml0ZSBjb21wYXJpc29uIHN0YXlzLCBiZWNhdXNlIGIyIGhhcyBubyBzZXJ2ZXIgb2Ygb3VycyBlbmZvcmNpbmcgb25seS10YWtlLXRoZS1sYXRlc3QgLSB3aXRob3V0IGl0IGEgc3RhbGUgcHVzaCBsYW5kcyBvdmVyIGEgbmV3ZXIgdmFsdWUgb3IgdG9tYnN0b25lIGFuZCBiMidzIHNlbGYtc3RhbXBlZCB1cGxvYWQgdGltZSBsYXVuZGVycyBpdCBpbnRvIHRoZSBuZXdlc3QgY29weSBpbiB0aGUgc3lzdGVtIChnbG9iYWwgcmVzdXJyZWN0aW9uKS4gSG9zdGVkIHRhcmdldHMgcmUtY2hlY2sgc2VydmVyLXNpZGUsIHNvIHRoZWlyIGNsaWVudC1zaWRlIHNob3J0Y3V0cyBhcmUgc2FmZS4gKi9cbiAgICBub0NoZWNrcz86IGJvb2xlYW47XG4gICAgLyoqIFN0b3JlLXRvLXN0b3JlIHB1c2g6IHRoZSByZWNlaXZpbmcgbm9kZSB3cml0ZXMgcHVyZWx5IHRvIGl0cyBvd24gZGlzayBhbmQgaW5kZXgsIHdpdGggTk8gZG93bnN0cmVhbSBmYW4tb3V0ICh0aGUgcHVzaGluZyBzdG9yZSBvd25zIHByb3BhZ2F0aW9uIC0gZmFubmluZyBpdHMgcHVzaGVzIGJhY2sgb3V0IGlzIGhvdyB3cml0ZSBsb29wcyBiZXR3ZWVuIHN0b3JlcyBmb3JtKS4gV2luZG93IGFuZCByb3V0ZSBBUkUgc3RpbGwgY2hlY2tlZDogdGhlIHN0YW1wIG11c3QgZmFsbCBpbnNpZGUgb25lIG9mIHRoZSByZWNlaXZlcidzIGNvbmZpZ3VyZWQgd2luZG93cyBhbmQgcm91dGVzLCBzbyBhIGNvbmZ1c2VkIHBlZXIgY2Fubm90IHN0dWZmIGRhdGEgb250byBhIG5vZGUgdGhhdCB3YXMgbmV2ZXIgbWVhbnQgdG8gaG9sZCBpdC4gUmVxdWlyZXMgbGFzdE1vZGlmaWVkLiAqL1xuICAgIGludGVybmFsPzogYm9vbGVhbjtcbiAgICAvKiogV3JpdGVzIG5vcm1hbGx5IGdvIE9OTFkgdG8gdGhlIHdyaXRlIG5vZGUgKHRoZSBmaXJzdCBjdXJyZW50LXdpbmRvdyBzb3VyY2UgY292ZXJpbmcgdGhlIGtleSksIHJldHJ5aW5nIGl0IGV2ZW4gd2hpbGUgaXQgaXMgZG93biAtIGNvbnNpc3RlbnQsIGJ1dCB1bmF2YWlsYWJsZSB3aGVuIHRoYXQgbm9kZSBpcy4gV2l0aCBmYWxsYmFja3MsIHRoZSB3cml0ZSBub2RlIGlzIHN0aWxsIHRyaWVkIGZpcnN0LCBidXQgb24gZmFpbHVyZSB0aGUgd3JpdGUgbGFuZHMgb24gdGhlIG5leHQgY3VycmVudC13aW5kb3cgc291cmNlIGNvdmVyaW5nIHRoZSBrZXkgKHN5bmNocm9uaXphdGlvbiBtb3ZlcyBpdCB0byB0aGUgd3JpdGUgbm9kZSBsYXRlcikgLSBhdmFpbGFiaWxpdHkgYXQgdGhlIGNvc3Qgb2YgcmVhZHMgcG9zc2libHkgbWlzc2luZyB0aGUgd3JpdGUgdW50aWwgaXQgcHJvcGFnYXRlcy4gU2luZ2xlLXNvdXJjZSBhcmNoaXZlcyBpZ25vcmUgdGhlIGZsYWcuICovXG4gICAgZmFsbGJhY2tzPzogYm9vbGVhbjtcbn07XG5cbi8vIGNyZWF0ZVRpbWUgaXMgYSBtaXNub21lciBrZXB0IGZvciBjb21wYXRpYmlsaXR5IOKAlCBpdCBpcyByZWFsbHkgdGhlIExBU1QtV1JJVEUgdGltZSwgc2FtZSBhcyBnZXRJbmZvJ3Mgd3JpdGVUaW1lLiBOZWl0aGVyIEJhY2tibGF6ZSBub3Igb3VyIHJlbW90ZSBzdG9yYWdlIHRyYWNrcyBhIGRpc3RpbmN0IGNyZWF0aW9uIGRhdGU6IGVhY2ggd3JpdGUgc3RhbXBzIGEgZnJlc2ggdGltZXN0YW1wIG9uIHRoZSBjdXJyZW50IHZlcnNpb24sIHNvIGJvdGggZmllbGRzIGFyZSBqdXN0IFwid2hlbiB0aGUgYnl0ZXMgc2VydmVkIGJ5IGdldCgpIHdlcmUgbW9zdCByZWNlbnRseSB3cml0dGVuXCIuXG5leHBvcnQgdHlwZSBBcmNoaXZlRmlsZUluZm8gPSB7IHBhdGg6IHN0cmluZzsgY3JlYXRlVGltZTogbnVtYmVyOyBzaXplOiBudW1iZXIgfTtcblxuLy8gQW4gaW4tcHJvZ3Jlc3MgYmFja2dyb3VuZCBzeW5jaHJvbml6YXRpb24gdGFzayAoc2VlIEFyY2hpdmVzQ29uZmlnLnN5bmNpbmcpXG5leHBvcnQgdHlwZSBTeW5jQWN0aXZpdHkgPSB7XG4gICAgLy8gQSBtZXRhZGF0YSBzY2FuIGlzIGEgc2luZ2xlIGxpc3RpbmcgY2FsbCwgc28gaXQgaGFzIG5vIGluY3JlbWVudGFsIHByb2dyZXNzIC0ganVzdCB0aGF0IGl0J3MgcnVubmluZyBhbmQgc2luY2Ugd2hlbi4gQSBmdWxsIHN5bmMga25vd3MgaXRzIGV4YWN0IGZpbGUvYnl0ZSBwcm9ncmVzcy5cbiAgICB0eXBlOiBcIm1ldGFkYXRhU2NhblwiIHwgXCJmdWxsU3luY1wiO1xuICAgIHNvdXJjZURlYnVnTmFtZTogc3RyaW5nO1xuICAgIHN0YXJ0VGltZTogbnVtYmVyO1xuICAgIGRvbmVGaWxlcz86IG51bWJlcjtcbiAgICB0b3RhbEZpbGVzPzogbnVtYmVyO1xuICAgIGRvbmVCeXRlcz86IG51bWJlcjtcbiAgICB0b3RhbEJ5dGVzPzogbnVtYmVyO1xufTtcblxuZXhwb3J0IHR5cGUgQXJjaGl2ZXNDb25maWcgPSB7XG4gICAgLy8gV2hldGhlciBnZXRDaGFuZ2VzQWZ0ZXIyIGlzIG5hdGl2ZWx5IGluZGV4LWJhY2tlZCAoZmFzdCBjaGFuZ2UgcG9sbGluZzsgZXZlcnkgYmFja2VuZCBzdGlsbCBzZXJ2ZXMgaXQsIGJ1dCB0aGUgb3RoZXJzIGVtdWxhdGUgaXQgd2l0aCBhIGZ1bGwgbGlzdGluZylcbiAgICBzdXBwb3J0c0NoYW5nZXNBZnRlcj86IGJvb2xlYW47XG4gICAgLy8gVGhlIGJ1Y2tldCdzIGZ1bGwgcm91dGluZyBjb25maWcgKFJPVVRJTkdfRklMRSkuIEFic2VudCBmb3Igc291cmNlcyB0aGF0IGRvbid0IGhhdmUgb25lIChhIGJhcmUgZGlzayBzb3VyY2UsIG9yIGEgYnVja2V0IHRoYXQgZG9lc24ndCBleGlzdCB5ZXQpLlxuICAgIHJlbW90ZUNvbmZpZz86IFJlbW90ZUNvbmZpZztcbiAgICAvLyBMaXZlIGluZGV4IHRvdGFscyAodG9tYnN0b25lcyBleGNsdWRlZCksIGtlcHQgdXAgdG8gZGF0ZSBpbiBtZW1vcnkgb24gZXZlcnkgbXV0YXRpb24gYW5kIHJlY29tcHV0ZWQgb24gbG9hZCAtIHNvIGFueSBkcmlmdCBoZWFscyBvbiByZXN0YXJ0XG4gICAgaW5kZXg/OiB7IGZpbGVDb3VudDogbnVtYmVyOyBieXRlQ291bnQ6IG51bWJlciB9O1xuICAgIC8vIFRoZSBzYW1lIHRvdGFscyBicm9rZW4gZG93biBieSB3aGljaCBzb3VyY2UgY3VycmVudGx5IGhvbGRzIGVhY2ggZmlsZSdzIGJ5dGVzICh0aGUgZmlyc3QgZW50cnkgaXMgdGhlIHNlcnZlcidzIG93biBkaXNrKVxuICAgIGluZGV4U291cmNlcz86IHsgZGVidWdOYW1lOiBzdHJpbmc7IGZpbGVDb3VudDogbnVtYmVyOyBieXRlQ291bnQ6IG51bWJlciB9W107XG4gICAgLy8gVGhlIHNlcnZlcidzIGNvbmZpZ3VyZWQgcmVhZGVyRGlza0xpbWl0LCB3aGVuIGl0IHJ1bnMgYXMgYSBib3VuZGVkIHJlYWQgY2FjaGVcbiAgICByZWFkZXJEaXNrTGltaXQ/OiBudW1iZXI7XG4gICAgLy8gQmFja2dyb3VuZCBzeW5jaHJvbml6YXRpb24gY3VycmVudGx5IGluIHByb2dyZXNzIChlbXB0eSB3aGVuIGlkbGUpXG4gICAgc3luY2luZz86IFN5bmNBY3Rpdml0eVtdO1xufTtcblxuLy8gQSBzeW5jaHJvbml6YXRpb24gc291cmNlIG9mIGEgQmxvYlN0b3JlICh3aGljaCBzeW5jaHJvbml6ZXMgYW4gaW5kZXggKyBsb2NhbCBjYWNoZSBmcm9tIHRoZW0pXG5leHBvcnQgdHlwZSBBcmNoaXZlc1NvdXJjZSA9IHtcbiAgICBzb3VyY2U6IElBcmNoaXZlcztcbiAgICAvKiogVGhlIHBlcnNpc3RlbnQgaWRlbnRpdHkgb2YgdGhlIGVuZHBvaW50OiBpdHMgcm91dGluZyBVUkwgKGhvc3RlZC9iYWNrYmxhemUpLCBvciB0aGUgZGlzayBmb2xkZXIgcGF0aCBmb3IgdGhlIGJhc2UgZGlzayBzb3VyY2UuIFRoZSBzdG9yZSBwZXJzaXN0cyB0aGlzICh2aWEgaXRzIGFwcGVuZC1vbmx5IHNvdXJjZXMgbGlzdCkgYXMgSW5kZXhFbnRyeS5zb3VyY2VzTGlzdEluZGV4LCBzbyBpdCBtdXN0IG1lYW4gdGhlIHNhbWUgZW5kcG9pbnQgZm9yZXZlci4gKi9cbiAgICB1cmw6IHN0cmluZztcbiAgICAvLyBGcm9tIHRoZSBzb3VyY2UncyBDb21tb25Db25maWcsIGJ1dCBBTEwgb2YgdGhlbTogdGhlIHNhbWUgZW5kcG9pbnQgKHNhbWUgdXJsK3JvdXRlLCBpZ25vcmluZyB0aGUgd2luZG93KSBjYW4gYXBwZWFyIGluIHRoZSByb3V0aW5nIGNvbmZpZyB1bmRlciBzZXZlcmFsIHdpbmRvd3MgYXQgb25jZSAtIG1vc3QgY29tbW9ubHkgd2hlbiBhIGRlcGxveSBzd2l0Y2hvdmVyIGhhcyBzcGxpdCBvbmUgd2luZG93IGluIHR3byBhcm91bmQgYW4gaW50ZXJtZWRpYXRlLiBJdCBpcyBPTkUgc291cmNlIHRoYXQga25vd3MgYWxsIGl0cyB3aW5kb3dzLCBuZXZlciBzZXZlcmFsIHNvdXJjZXMuIFRoZSB3aW5kb3cgcm91dGVzIFdSSVRFUzogdGhlIHNvdXJjZSByZWNlaXZlcyB3cml0ZXMgd2hpbGUgQU5ZIG9mIGl0cyB3aW5kb3dzIGlzIHN0aWxsIG9wZW4gKHNlZSB3aW5kb3dzQWNjZXB0V3JpdGVzKS4gV2luZG93cyBkbyBOT1QgZmlsdGVyIHNjYW5uaW5nOiBhIHNjYW4gaXMgdXMgYXNraW5nIHRoZSBzb3VyY2Ugd2hhdCBpdCBhbHJlYWR5IGhvbGRzLCBhbmQgZXhpc3RpbmcgdmFsdWVzIHN5bmNocm9uaXplIHJlZ2FyZGxlc3Mgb2YgdGhlaXIgd3JpdGUgdGltZXMgKHRoZSBzYW1lIHJlYXNvbmluZyB0aGF0IGxldHMgc3luY2hyb25pemF0aW9uIGlnbm9yZSB0aGUgaW1tdXRhYmxlIGZsYWcpLlxuICAgIHZhbGlkV2luZG93czogW251bWJlciwgbnVtYmVyXVtdO1xuICAgIC8vIEZyb20gdGhlIHNvdXJjZSdzIENvbW1vbkNvbmZpZyAoaW50ZXJzZWN0ZWQgd2l0aCB0aGUgb3duaW5nIHN0b3JlJ3Mgb3duIHJvdXRlKTogb25seSBrZXlzIHJvdXRpbmcgaW50byBbc3RhcnQsIGVuZCkgYXJlIGFjY2VwdGVkIGZyb20gdGhpcyBzb3VyY2UncyBzY2FucyBhbmQgc2VudCB0byBpdCBpbiB3cml0ZXMvcmVjb25jaWxpYXRpb24uIFRoZSByb3V0aW5nIGZpbGUgaXMgZXhlbXB0IC0gY29uZmlnIGZsb3dzIGV2ZXJ5d2hlcmUuIEFic2VudCA9IGFsbCBrZXlzLlxuICAgIHJvdXRlPzogW251bWJlciwgbnVtYmVyXTtcbiAgICAvLyBGcm9tIHRoZSBzb3VyY2UncyBDb21tb25Db25maWc7IHNlZSB0aGVyZS5cbiAgICBub0Z1bGxTeW5jPzogYm9vbGVhbjtcbiAgICAvLyBGcm9tIHRoZSBzb3VyY2UncyBDb21tb25Db25maWc6IGEgZGVwbG95IHN3aXRjaG92ZXIncyB0ZW1wb3JhcnkgYWx0ZXJuYXRlLXBvcnQgZW50cnkuIE9uY2UgaXRzIHdpbmRvdyBpcyBwYXN0LCB0aGUgcG9ydCBpdCBwb2ludHMgYXQgaXMgZ29uZSBmb3IgZ29vZCAtIHNvIGl0IGlzIG5ldmVyIHNjYW5uZWQgdGhlbiwgYW5kIHNjYW4gZmFpbHVyZXMgYXJlIG5ldmVyIHJldHJpZWQuXG4gICAgaW50ZXJtZWRpYXRlPzogYm9vbGVhbjtcbiAgICAvLyBUaGUgcm91dGluZy1jb25maWcgZW50cnkgdGhpcyBzb3VyY2Ugd2FzIGJ1aWx0IGZyb20gKGFic2VudCBmb3IgdGhlIGJhc2UgZGlzayBzb3VyY2UpLiBJdHMgYHR5cGVgIGRlY2lkZXMgZmFzdC13cml0ZSBmbHVzaCB0aW1pbmc6IHR5cGUtXCJyZW1vdGVcIiBkb3duc3RyZWFtIHNvdXJjZXMgKG91ciBvd24gc3RvcmFnZSBzZXJ2ZXJzKSBmbHVzaCBxdWlja2x5IChjaGVhcCwgYW5kIHdlIHdhbnQgY3Jvc3Mtbm9kZSByZWR1bmRhbmN5IGZhc3QpLCB3aGlsZSBvdGhlcnMgKGUuZy4gYmFja2JsYXplKSBrZWVwIHRoZSBmdWxsIHdyaXRlRGVsYXkgc28gZXhwZW5zaXZlIGV4dGVybmFsIHdyaXRlcyBzdGF5IGNvYWxlc2NlZC4gVGhlIHdpbmRvdy9yb3V0ZSBPTiB0aGlzIGNvbmZpZyBhcmUgdGhlIFNPVVJDRSdzIG93bjsgQXJjaGl2ZXNTb3VyY2UudmFsaWRXaW5kb3cvcm91dGUgYXJlIHdoYXQgdGhlIG93bmluZyBzdG9yZSBhY3R1YWxseSB1c2VzIChyb3V0ZSBpcyBpbnRlcnNlY3RlZCB3aXRoIHRoZSBzdG9yZSdzIHJvdXRlKS5cbiAgICBzb3VyY2VDb25maWc/OiBTb3VyY2VDb25maWc7XG4gICAgLy8gU3RhYmxlIGlkZW50aXR5IG9mIHRoZSB1bmRlcmx5aW5nIGVuZHBvaW50IChpdHMgY29uZmlnIHdpdGggd2luZG93cy9yb3V0ZXMgc3RyaXBwZWQpIC0gaG93IEJsb2JTdG9yZS51cGRhdGVTb3VyY2VzIHJlY29nbml6ZXMgYSBzb3VyY2UgYWNyb3NzIGNvbmZpZyBjaGFuZ2VzIHNvIGl0IGNhbiB1cGRhdGUgaXQgaW4gcGxhY2UgaW5zdGVhZCBvZiByZW1vdmluZyBhbmQgcmUtYWRkaW5nIGl0XG4gICAgaWRlbnRpdHk/OiBzdHJpbmc7XG59O1xuXG4vLyBFcnJvciBtYXJrZXIgYSBzZXJ2ZXIgaW5jbHVkZXMgd2hlbiBhIGZyZXNobHktc3RhbXBlZCB3cml0ZSByZWFjaGVzIGl0IG91dHNpZGUgaXRzIHZhbGlkIHdpbmRvd3MgKHRoZSBjbGllbnQgcmVzb2x2ZWQgaXRzIHRhcmdldCwgdGhlbiB0aW1lIGNyb3NzZWQgYSB3aW5kb3cgYm91bmRhcnkgYmVmb3JlIHRoZSB3cml0ZSBsYW5kZWQpLiBDbGllbnRzIGRldGVjdCB0aGlzIG1hcmtlciBhbmQgcmUtcmVzb2x2ZSB0aGUgY3VycmVudGx5LXZhbGlkIHNvdXJjZSwgcmV0cnlpbmcgT05DRSAtIGJvdW5kYXJpZXMgYXJlIGZhciBhcGFydCwgc28gaGl0dGluZyBpdCB0d2ljZSBpbiBvbmUgYXR0ZW1wdCBtZWFucyBzb21ldGhpbmcgaXMgYWN0dWFsbHkgd3JvbmcuXG5leHBvcnQgY29uc3QgU1RPUkFHRV9XUk9OR19WQUxJRF9XSU5ET1cgPSBcIlJFTU9URV9TVE9SQUdFX1dST05HX1ZBTElEX1dJTkRPV19hN2MxZjA0ZVwiO1xuXG4vLyBFcnJvciBtYXJrZXIgYSBzZXJ2ZXIgaW5jbHVkZXMgd2hlbiBhIGZyZXNobHktc3RhbXBlZCB3cml0ZSdzIGtleSByb3V0ZXMgb3V0c2lkZSB0aGUgc2hhcmRzIHRoaXMgc2VydmVyIGhhbmRsZXMgKHRoZSBjbGllbnQncyBjb25maWcgZGlzYWdyZWVzIHdpdGggdGhlIHNlcnZlcidzIC0gY2xpZW50cyByZS1yZXNvbHZlIG9uY2UpXG5leHBvcnQgY29uc3QgU1RPUkFHRV9XUk9OR19ST1VURSA9IFwiUkVNT1RFX1NUT1JBR0VfV1JPTkdfUk9VVEVfYzk0ZDJlMTdcIjtcblxuZXhwb3J0IGNvbnN0IEZVTExfUk9VVEU6IFtudW1iZXIsIG51bWJlcl0gPSBbMCwgMV07XG5cbi8vIEEga2V5IGNvbnRhaW5pbmcgdGhpcyBzZW50aW5lbCBkb2Vzbid0IGhhdmUgYSBmaXhlZCBzaGFyZDogc2V0VmFyaWFibGVTaGFyZCBwaWNrcyB0aGUgKGxvd2VzdCBsYXRlbmN5LCB1cCkgd3JpdGUgc2hhcmQsIGFwcGVuZHMgXCJfPHZhbHVlIGluIHRoZSBzaGFyZCdzIHJvdXRlPlwiIGRpcmVjdGx5IGFmdGVyIHRoZSBzZW50aW5lbCwgYW5kIHJldHVybnMgdGhlIG1hdGVyaWFsaXplZCBrZXkuIGdldFJvdXRlIHRyZWF0cyB0aGF0IHN1ZmZpeCBhcyBhIGNvbXBsZXRlIHJvdXRlIG92ZXJyaWRlLlxuZXhwb3J0IGNvbnN0IFZBUklBQkxFX1NIQVJEID0gXCJWQVJJQUJMRV9TSEFSRF9mMDIzNGpmYWgwOGZneWhmZ3lzc2Rkczgzbm1wXCI7XG4vLyBObyBncmFjZSBwYXN0IHRoZSBlbmQ6IGEgd2luZG93IGJvdW5kYXJ5IGlzIGEgaGFyZCBoYW5kb2ZmIChjbGllbnRzIHJldHJ5IGEgcmVqZWN0ZWQgd3JpdGUgYWdhaW5zdCB0aGUgbmV3bHktdmFsaWQgc291cmNlLCBzbyBsZW5pZW5jeSBoZXJlIHdvdWxkIG9ubHkgZGVzeW5jaHJvbml6ZSB0aGUgaGFuZG9mZilcbi8vICAtIFdyaXRpbmcgdG8gb2xkZXIgdmFsaWQgc3RhdGUgd2luZG93cyBpcyBmaW5lLCB0aG91Z2guIFdlIG5lZWQgdGhpcyB0byBpbmdlc3QgdGhlIG9sZCBkYXRhIHdoZW4gd2UncmUgc3luY2hyb25pemluZyBub2RlcyB0byBnZXQgdGhlbSB1cCB0byBkYXRlIGFueXdheS4gXG5leHBvcnQgZnVuY3Rpb24gd2luZG93QWNjZXB0c1dyaXRlcyh2YWxpZFdpbmRvdzogW251bWJlciwgbnVtYmVyXSB8IHVuZGVmaW5lZCk6IGJvb2xlYW4ge1xuICAgIGlmICghdmFsaWRXaW5kb3cpIHJldHVybiB0cnVlO1xuICAgIHJldHVybiB2YWxpZFdpbmRvd1sxXSA+IERhdGUubm93KCk7XG59XG4vLyBBIHNvdXJjZSAod2hpY2ggY2FuIGhvbGQgc2V2ZXJhbCB3aW5kb3dzKSBhY2NlcHRzIHdyaXRlcyB3aGlsZSBBTlkgb2YgaXRzIHdpbmRvd3MgaXMgc3RpbGwgb3Blbi4gTm8gd2luZG93cyA9IHRoZSBiYXNlIGRpc2sgb2YgYW4gaW5lcnQgc3RvcmUgKG5vdCBpbiB0aGUgY29uZmlnKSwgd2hpY2ggbmV2ZXIgcmVjZWl2ZXMgZmFuLW91dCB3cml0ZXMgYW55d2F5LlxuZXhwb3J0IGZ1bmN0aW9uIHdpbmRvd3NBY2NlcHRXcml0ZXModmFsaWRXaW5kb3dzOiBbbnVtYmVyLCBudW1iZXJdW10pOiBib29sZWFuIHtcbiAgICByZXR1cm4gdmFsaWRXaW5kb3dzLnNvbWUod2luZG93QWNjZXB0c1dyaXRlcyk7XG59XG5cbmNvbnN0IExBUkdFX0NPUFlfVEhSRVNIT0xEID0gNjQgKiAxMDI0ICogMTAyNDtcbmNvbnN0IExBUkdFX0NPUFlfQ0hVTksgPSAzMiAqIDEwMjQgKiAxMDI0O1xuXG4vLyBBYm92ZSB0aGlzLCBzZXQgdHJhbnNwYXJlbnRseSBzdHJlYW1zIHRocm91Z2ggc2V0TGFyZ2VGaWxlOiBvbmUgZ2lhbnQgd2lyZSBtZXNzYWdlIHdvdWxkIGV4Y2VlZCB0aGUgdHJhbnNwb3J0IGxpbWl0IGFuZCBsYWcgZXZlcnkgb3RoZXIgY2xpZW50IHNoYXJpbmcgdGhlIGNvbm5lY3Rpb25cbmV4cG9ydCBjb25zdCBMQVJHRV9TRVRfVEhSRVNIT0xEID0gOCAqIDEwMjQgKiAxMDI0O1xuXG4vKiogQSBnZXROZXh0RGF0YSBzdHJlYW0gb3ZlciBhbiBpbi1tZW1vcnkgYnVmZmVyLCBpbiBMQVJHRV9TRVRfVEhSRVNIT0xEIHNsaWNlcyAtIGhvdyBzZXQgdHJhbnNwYXJlbnRseSBiZWNvbWVzIHNldExhcmdlRmlsZSBmb3IgbGFyZ2UgYnVmZmVycy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidWZmZXJDaHVua1N0cmVhbShkYXRhOiBCdWZmZXIpOiAoKSA9PiBQcm9taXNlPEJ1ZmZlciB8IHVuZGVmaW5lZD4ge1xuICAgIGxldCBvZmZzZXQgPSAwO1xuICAgIHJldHVybiBhc3luYyAoKSA9PiB7XG4gICAgICAgIGlmIChvZmZzZXQgPj0gZGF0YS5sZW5ndGgpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIGxldCBjaHVuayA9IGRhdGEuc3ViYXJyYXkob2Zmc2V0LCBvZmZzZXQgKyBMQVJHRV9TRVRfVEhSRVNIT0xEKTtcbiAgICAgICAgb2Zmc2V0ICs9IGNodW5rLmxlbmd0aDtcbiAgICAgICAgcmV0dXJuIGNodW5rO1xuICAgIH07XG59XG5cbi8qKiBDb3BpZXMgb25lIGZpbGUgYmV0d2VlbiB0d28gYXJjaGl2ZXMuIFNtYWxsIGZpbGVzIGdvIGFzIGEgc2luZ2xlIGdldDIrc2V0OyBwYXN0IExBUkdFX0NPUFlfVEhSRVNIT0xEIHRoZSBjb3B5IHN0cmVhbXMgdGhyb3VnaCBzZXRMYXJnZUZpbGUgaW4gTEFSR0VfQ09QWV9DSFVOSyByYW5nZWQgcmVhZHMsIHNvIHRoZSB3aG9sZSBmaWxlIGlzIG5ldmVyIGluIG1lbW9yeS4gc2l6ZS93cml0ZVRpbWUgdXN1YWxseSBjb21lIGZyb20gdGhlIGNhbGxlcidzIG1ldGFkYXRhIHNjYW47IHdoZW4gZWl0aGVyIGlzIG9taXR0ZWQsIGdldEluZm8gZmlsbHMgdGhlbSBpbi4gUmV0dXJucyB0aGUgY29waWVkIGZpbGUncyBpbmZvLCBvciB1bmRlZmluZWQgd2hlbiB0aGUgc291cmNlIGRvZXNuJ3QgaGF2ZSB0aGUgZmlsZS4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjb3B5QXJjaGl2ZUZpbGUoY29uZmlnOiB7XG4gICAgZnJvbTogSUFyY2hpdmVzO1xuICAgIHRvOiBJQXJjaGl2ZXM7XG4gICAgcGF0aDogc3RyaW5nO1xuICAgIHNpemU/OiBudW1iZXI7XG4gICAgd3JpdGVUaW1lPzogbnVtYmVyO1xuICAgIGZvcmNlU2V0SW1tdXRhYmxlPzogYm9vbGVhbjtcbiAgICBub0NoZWNrcz86IGJvb2xlYW47XG4gICAgaW50ZXJuYWw/OiBib29sZWFuO1xuICAgIG5vRmFsbGJhY2tzPzogYm9vbGVhbjtcbn0pOiBQcm9taXNlPHsgd3JpdGVUaW1lOiBudW1iZXI7IHNpemU6IG51bWJlciB9IHwgdW5kZWZpbmVkPiB7XG4gICAgbGV0IHsgZnJvbSwgdG8sIHBhdGggfSA9IGNvbmZpZztcbiAgICBsZXQgc2l6ZSA9IGNvbmZpZy5zaXplO1xuICAgIGxldCB3cml0ZVRpbWUgPSBjb25maWcud3JpdGVUaW1lO1xuICAgIGlmIChzaXplID09PSB1bmRlZmluZWQgfHwgd3JpdGVUaW1lID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgbGV0IGluZm8gPSBhd2FpdCBmcm9tLmdldEluZm8ocGF0aCwgeyBub0ZhbGxiYWNrczogY29uZmlnLm5vRmFsbGJhY2tzIH0pO1xuICAgICAgICBpZiAoIWluZm8pIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIHNpemUgPSBpbmZvLnNpemU7XG4gICAgICAgIHdyaXRlVGltZSA9IGluZm8ud3JpdGVUaW1lO1xuICAgIH1cbiAgICBpZiAoc2l6ZSA8PSBMQVJHRV9DT1BZX1RIUkVTSE9MRCkge1xuICAgICAgICBsZXQgcmVzdWx0ID0gYXdhaXQgZnJvbS5nZXQyKHBhdGgsIHsgaW50ZXJuYWw6IGNvbmZpZy5pbnRlcm5hbCwgbm9GYWxsYmFja3M6IGNvbmZpZy5ub0ZhbGxiYWNrcyB9KTtcbiAgICAgICAgLy8gRW1wdHkgY291bnRzIGFzIGFic2VudCwgbmV2ZXIgYXMgY29udGVudCB0byBjb3B5OiBhbiBlbXB0eSBmaWxlIElTIGEgZGVsZXRpb24sIHNldCByZWZ1c2VzIGVtcHR5IGJ1ZmZlcnMsIGFuZCBkZWxldGlvbnMgdHJhdmVsIHRocm91Z2ggdGhlaXIgb3duIHBhdGggKGRlbCAvIHNjYW4gdG9tYnN0b25lcylcbiAgICAgICAgaWYgKCFyZXN1bHQgfHwgIXJlc3VsdC5kYXRhIHx8ICFyZXN1bHQuZGF0YS5sZW5ndGgpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIGF3YWl0IHRvLnNldChwYXRoLCByZXN1bHQuZGF0YSwgeyBsYXN0TW9kaWZpZWQ6IHJlc3VsdC53cml0ZVRpbWUsIGZvcmNlU2V0SW1tdXRhYmxlOiBjb25maWcuZm9yY2VTZXRJbW11dGFibGUsIG5vQ2hlY2tzOiBjb25maWcubm9DaGVja3MsIGludGVybmFsOiBjb25maWcuaW50ZXJuYWwgfSk7XG4gICAgICAgIHJldHVybiB7IHdyaXRlVGltZTogcmVzdWx0LndyaXRlVGltZSwgc2l6ZTogcmVzdWx0LmRhdGEubGVuZ3RoIH07XG4gICAgfVxuICAgIC8vIENvbnN0cyBzbyB0aGUgY2xvc3VyZSBrZWVwcyB0aGUgbmFycm93ZWQgdHlwZXNcbiAgICBjb25zdCB0b3RhbFNpemUgPSBzaXplO1xuICAgIGNvbnN0IGZpbmFsV3JpdGVUaW1lID0gd3JpdGVUaW1lO1xuICAgIGxldCBvZmZzZXQgPSAwO1xuICAgIGF3YWl0IHRvLnNldExhcmdlRmlsZSh7XG4gICAgICAgIHBhdGgsXG4gICAgICAgIGxhc3RNb2RpZmllZDogZmluYWxXcml0ZVRpbWUsXG4gICAgICAgIGdldE5leHREYXRhOiBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBpZiAob2Zmc2V0ID49IHRvdGFsU2l6ZSkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGxldCBlbmQgPSBNYXRoLm1pbihvZmZzZXQgKyBMQVJHRV9DT1BZX0NIVU5LLCB0b3RhbFNpemUpO1xuICAgICAgICAgICAgbGV0IGRhdGEgPSBhd2FpdCBmcm9tLmdldChwYXRoLCB7IHJhbmdlOiB7IHN0YXJ0OiBvZmZzZXQsIGVuZCB9LCBpbnRlcm5hbDogY29uZmlnLmludGVybmFsLCBub0ZhbGxiYWNrczogY29uZmlnLm5vRmFsbGJhY2tzIH0pO1xuICAgICAgICAgICAgaWYgKCFkYXRhIHx8ICFkYXRhLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgUmFuZ2VkIHJlYWQgb2YgJHtKU09OLnN0cmluZ2lmeShwYXRoKX0gZnJvbSAke2Zyb20uZ2V0RGVidWdOYW1lKCl9IHJldHVybmVkICR7ZGF0YSAmJiBkYXRhLmxlbmd0aCB8fCBcIm5vdGhpbmdcIn0gYXQgJHtvZmZzZXR9LSR7ZW5kfSAoZXhwZWN0ZWQgJHtlbmQgLSBvZmZzZXR9IGJ5dGVzIG9mIGEgJHt0b3RhbFNpemV9IGJ5dGUgZmlsZSAtIGl0IGNoYW5nZWQgb3IgdmFuaXNoZWQgbWlkLWNvcHkpYCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvZmZzZXQgKz0gZGF0YS5sZW5ndGg7XG4gICAgICAgICAgICByZXR1cm4gZGF0YTtcbiAgICAgICAgfSxcbiAgICB9KTtcbiAgICByZXR1cm4geyB3cml0ZVRpbWU6IGZpbmFsV3JpdGVUaW1lLCBzaXplOiB0b3RhbFNpemUgfTtcbn1cblxuZXhwb3J0IHR5cGUgQXJjaGl2ZXNTeW5jU291cmNlU3RhdHVzID0ge1xuICAgIGRlYnVnTmFtZTogc3RyaW5nO1xuICAgIHZhbGlkV2luZG93czogW251bWJlciwgbnVtYmVyXVtdO1xuICAgIHJvdXRlPzogW251bWJlciwgbnVtYmVyXTtcbiAgICBub0Z1bGxTeW5jPzogYm9vbGVhbjtcbiAgICBzdXBwb3J0c0NoYW5nZXNBZnRlcjogYm9vbGVhbjtcbiAgICBpbml0aWFsU2NhbkNvbXBsZXRlOiBib29sZWFuO1xuICAgIC8vIEZpbGVzIHNlZW4gaW4gdGhpcyBzb3VyY2UncyBzY2FucyAvIGNoYW5nZSBwb2xscyBzbyBmYXJcbiAgICBzY2FubmVkQ291bnQ6IG51bWJlcjtcbn07XG5leHBvcnQgdHlwZSBBcmNoaXZlc1N5bmNTdGF0dXMgPSB7XG4gICAgYWxsU2NhbnNDb21wbGV0ZTogYm9vbGVhbjtcbiAgICAvLyBOdW1iZXIgb2YgZmlsZXMgaW4gdGhlIGluZGV4XG4gICAgaW5kZXhTaXplOiBudW1iZXI7XG4gICAgc291cmNlczogQXJjaGl2ZXNTeW5jU291cmNlU3RhdHVzW107XG59O1xuXG4vLyBOT1RFOiBXZSBkb24ndCBwcmVzZW50bHkgaGF2ZSBhbiBhcHBlbmQgZnVuY3Rpb24gaGVyZSBiZWNhdXNlIGEgc3VycHJpc2luZyBudW1iZXIgb2Ygc3RvcmFnZSBzeXN0ZW1zIGRvbid0IHN1cHBvcnQgaXQgKGJhY2tibGF6ZSwgZmlsZSBzeXN0ZW0gYXBpKS4gSXQgd291bGQgYWxzbyBjb21wbGljYXRlIHRoaW5ncyBhcyBub3cgdGhlcmUgbmVlZHMgdG8gYmUgcmVhbGx5IGEgc2luZ2xlIHNvdXJjZSBvZiB0cnV0aCBvZiBhIGZpbGUsIGFuZCBpZiB5b3UgYXBwZW5kIHRvIHRoZSB3cm9uZyBzaW5nbGUgc291cmNlIG9mIHRydXRoLCB0aGluZ3MganVzdCBiZWNvbWUgdmVyeSBjb21wbGljYXRlZC4gXG5leHBvcnQgaW50ZXJmYWNlIElBcmNoaXZlcyB7XG4gICAgZ2V0RGVidWdOYW1lKCk6IHN0cmluZztcbiAgICAvKiogV2hldGhlciB3cml0ZXMgd291bGQgYmUgYWNjZXB0ZWQgKGNyZWRlbnRpYWxzIGV4aXN0LCB0aGUgYWNjb3VudCB0cnVzdHMgdGhpcyBtYWNoaW5lLCBldGMpLiBDaGVja2VkIHdpdGhvdXQgd3JpdGluZyBhbnl0aGluZy4gKi9cbiAgICBoYXNXcml0ZUFjY2VzcygpOiBQcm9taXNlPGJvb2xlYW4+O1xuICAgIC8qKlxuICAgICAqIFJlYWRzIGF1dG9tYXRpY2FsbHkgZmFsbCBiYWNrIGFjcm9zcyB0aGUgcmVkdW5kYW50IHNvdXJjZXMgdW5sZXNzIGNvbmZpZy5ub0ZhbGxiYWNrcyBpcyBzZXQuXG4gICAgICogQSBmYWxsYmFjayBjb3B5IGNhbiBsYWcgdGhlIHdyaXRlIHRhcmdldCwgc28gYSBjYWxsZXIgcmVhZGluZyBzdGF0ZSBpbiBvcmRlciB0byBtdXRhdGUgaXRcbiAgICAgKiAoZS5nLiB4KyspLCB3aGVyZSBhY3Rpbmcgb24gcHJldmlvdXMgc3RhdGUgd291bGQgY2F1c2UgYmlnIGlzc3Vlcywgc2hvdWxkIHBhc3Mgbm9GYWxsYmFja3MgLVxuICAgICAqIGFuZCB0cnkvY2F0Y2ggdGhlIHJlYWQsIGhhbmRsaW5nIHRoZSBjYXRjaCBjYXNlIChhIGRvd24gcHJpbWFyeSBpcyByZXRyaWVkIGZvciBhIHdoaWxlLCB0aGVuXG4gICAgICogdGhyb3dzIGluc3RlYWQgb2YgZGVncmFkaW5nIHRvIGEgc3RhbGUgY29weSkuXG4gICAgICovXG4gICAgZ2V0KGZpbGVOYW1lOiBzdHJpbmcsIGNvbmZpZz86IEdldENvbmZpZyk6IFByb21pc2U8QnVmZmVyIHwgdW5kZWZpbmVkPjtcbiAgICAvKiogU2VlIGdldCBmb3IgdGhlIGZhbGxiYWNrIHNlbWFudGljcyAoYW5kIHdoZW4gdG8gcGFzcyBub0ZhbGxiYWNrcykuIHVybCBpcyB0aGUgY29uZmlnIFVSTCBvZiB0aGUgc291cmNlIHRoYXQgYW5zd2VyZWQgLSB0aGUgYXV0aG9yaXR5IHRoZSBkYXRhIChvciB0aGUgXCJkb2VzIG5vdCBleGlzdFwiKSBjYW1lIGZyb20uIE11bHRpLXNvdXJjZSBpbXBsZW1lbnRhdGlvbnMgKEFyY2hpdmVzQ2hhaW4pIEFMV0FZUyByZXR1cm4gYW4gb2JqZWN0OiB3aGVuIHRoZSB2YWx1ZSBkb2Vzbid0IGV4aXN0IHRoZXJlIGlzIHN0aWxsIGEgc2VydmVyIHNheWluZyBpdCBkb2Vzbid0IGV4aXN0LCBzbyB0aGV5IHJldHVybiB7IHVybCB9IGFsb25lIHJhdGhlciB0aGFuIHVuZGVmaW5lZC4gU2luZ2xlLXNvdXJjZSBiYWNrZW5kcyByZXR1cm4gdW5kZWZpbmVkIGZvciBhYnNlbnQgKHRoZXkgQVJFIHRoZSBhdXRob3JpdHkpLiAqL1xuICAgIGdldDIoZmlsZU5hbWU6IHN0cmluZywgY29uZmlnPzogR2V0Q29uZmlnKTogUHJvbWlzZTx7IGRhdGE6IEJ1ZmZlcjsgd3JpdGVUaW1lOiBudW1iZXI7IHNpemU6IG51bWJlcjsgdXJsPzogc3RyaW5nIH0gfCB7IGRhdGE/OiB1bmRlZmluZWQ7IHdyaXRlVGltZT86IHVuZGVmaW5lZDsgc2l6ZT86IHVuZGVmaW5lZDsgdXJsOiBzdHJpbmcgfSB8IHVuZGVmaW5lZD47XG4gICAgLyoqXG4gICAgICogbGFzdE1vZGlmaWVkIHN0YW1wcyB0aGUgd3JpdGUgd2l0aCB0aGF0IGxhc3Qtd3JpdGUgdGltZSBpbnN0ZWFkIG9mIG5vdy4gSWYgaXQgaXMgT0xERVIgdGhhblxuICAgICAqIHRoZSBmaWxlJ3MgY3VycmVudCBsYXN0LXdyaXRlIHRpbWUgdGhlIHdyaXRlIG5vLW9wcyAoc28gZGVsYXllZCAvIHN5bmNocm9uaXplZCB3cml0ZXMgY2FuXG4gICAgICogbmV2ZXIgY2xvYmJlciBuZXdlciBkYXRhKS4gVGltZXMgbW9yZSB0aGFuIDE1IG1pbnV0ZXMgaW4gdGhlIGZ1dHVyZSBhcmUgcmVqZWN0ZWQuXG4gICAgICpcbiAgICAgKiBSZXR1cm5zIHRoZSBmdWxsIGtleSBhY3R1YWxseSB3cml0dGVuIC0gaWRlbnRpY2FsIHRvIGZpbGVOYW1lLCBFWENFUFQgZm9yIGtleXMgY29udGFpbmluZ1xuICAgICAqIFZBUklBQkxFX1NIQVJELCB3aGVyZSB0aGUgc2hhcmQgdmFsdWUgaXMgbWF0ZXJpYWxpemVkIGludG8gdGhlIGtleSAocGlja2VkIGJ5IHNoYXJkIGxhdGVuY3ksXG4gICAgICogc2VlIEFyY2hpdmVzQ2hhaW4pIGFuZCB0aGUgY2FsbGVyIG5lZWRzIHRoZSByZXR1cm5lZCBrZXkgdG8gZXZlciByZWFkIHRoZSB2YWx1ZSBiYWNrLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIFRIUk9XUyBvbiBhbiBlbXB0eSBidWZmZXI6IGFuIGVtcHR5IGZpbGUgSVMgYSBkZWxldGlvbiBpbiB0aGlzIHN5c3RlbSAodGhlIHRvbWJzdG9uZSksIHNvIGFcbiAgICAgKiBzZXQtZW1wdHkgd291bGQgcmVhZCBiYWNrIGFzIFwidGhlIGZpbGUgaXMgZ29uZVwiIC0gd2hpY2ggaXMganVzdCBhc2tpbmcgZm9yIHByb2JsZW1zLiBJZiB5b3VcbiAgICAgKiB3YW50IHRoZSBmaWxlIGRlbGV0ZWQsIGNhbGwgZGVsOyBkZWxldGlvbnMgdGFrZSB0aGVpciBvd24gcGF0aC5cbiAgICAgKi9cbiAgICBzZXQoZmlsZU5hbWU6IHN0cmluZywgZGF0YTogQnVmZmVyLCBjb25maWc/OiBTZXRDb25maWcpOiBQcm9taXNlPHN0cmluZz47XG4gICAgZGVsKGZpbGVOYW1lOiBzdHJpbmcsIGNvbmZpZz86IERlbENvbmZpZyk6IFByb21pc2U8dm9pZD47XG4gICAgLyoqIFN0cmVhbXMgYSBmaWxlIHRvbyBsYXJnZSB0byBob2xkIGluIG1lbW9yeS4gZ2V0TmV4dERhdGEgcmV0dXJucyB1bmRlZmluZWQgd2hlbiBkb25lLiBUaGlzIG9ubHkgbmVlZHMgdG8gYmUgY2FsbGVkIHdoZW4geW91IENBTk5PVCBtYXRlcmlhbGl6ZSB0aGUgZW50aXJlIGZpbGUgaW4gbWVtb3J5IC0gaWYgeW91IGNhbiwganVzdCBjYWxsIHNldDogYWJvdmUgTEFSR0VfU0VUX1RIUkVTSE9MRCBpdCBzdHJlYW1zIHRocm91Z2ggc2V0TGFyZ2VGaWxlIGludGVybmFsbHksIGtlZXBpbmcgdGhlIGNsaWVudCByZXNwb25zaXZlIGFuZCBub3Qgb3ZlcndoZWxtaW5nIHRoZSBzZXJ2ZXIuIGxhc3RNb2RpZmllZCBzdGFtcHMgdGhlIGZpbmlzaGVkIGZpbGUgbGlrZSBzZXQncyAoc3luY2hyb25pemVkIGNvcGllcyBuZWVkIGl0IHRvIGtlZXAgd3JpdGUgb3JkZXJpbmcpOyBiYWNrZW5kcyB0aGF0IHN0YW1wIHRoZWlyIG93biB0aW1lcyAoYmFja2JsYXplKSBhY2NlcHQgYW5kIGlnbm9yZSBpdC4gVEhST1dTIHdoZW4gdGhlIHN0cmVhbSBwcm9kdWNlcyBubyBkYXRhIGF0IGFsbCAtIHNhbWUgcnVsZSBhcyBzZXQ6IGFuIGVtcHR5IGZpbGUgSVMgYSBkZWxldGlvbiBhbmQgd291bGQgcmVhZCBiYWNrIGFzIG1pc3NpbmcuICovXG4gICAgc2V0TGFyZ2VGaWxlKGNvbmZpZzogeyBwYXRoOiBzdHJpbmc7IGxhc3RNb2RpZmllZD86IG51bWJlcjsgZ2V0TmV4dERhdGEoKTogUHJvbWlzZTxCdWZmZXIgfCB1bmRlZmluZWQ+IH0pOiBQcm9taXNlPHZvaWQ+O1xuICAgIC8qKiB3cml0ZVRpbWUgaXMgdGhlIGxhc3Qtd3JpdGUgdGltZSDigJQgc2VlIEFyY2hpdmVGaWxlSW5mby5jcmVhdGVUaW1lLCB3aGljaCBpcyB0aGUgc2FtZSB2YWx1ZS4gdXJsIGFzIGluIGdldDIuIFNpemUtMCBlbnRyaWVzICh0b21ic3RvbmVzKSByZXBvcnQgdW5kZWZpbmVkIHVubGVzcyBjb25maWcuaW5jbHVkZVRvbWJzdG9uZXMuICovXG4gICAgZ2V0SW5mbyhmaWxlTmFtZTogc3RyaW5nLCBjb25maWc/OiBHZXRJbmZvQ29uZmlnKTogUHJvbWlzZTx7IHdyaXRlVGltZTogbnVtYmVyOyBzaXplOiBudW1iZXI7IHVybD86IHN0cmluZyB9IHwgdW5kZWZpbmVkPjtcbiAgICAvKipcbiAgICAgKiBFbXB0eSAoc2l6ZS0wKSBmaWxlcyBhcmUgTkVWRVIgcmV0dXJuZWQgYnkgaW5kZXgtYmFja2VkIHN0b3JlcyAoQmxvYlN0b3JlLCBhbmQgdGhlcmVmb3JlIHRoZVxuICAgICAqIGNoYWluKTogYW4gZW1wdHkgZmlsZSBJUyBhIG1pc3NpbmcgZmlsZSAtIHRoZSB0b21ic3RvbmUgb2YgYSBkZWxldGlvbi4gSWYgeW91IHdhbnQgYSBtYXJrZXJcbiAgICAgKiBmaWxlIHRoYXQgc2hvd3MgdXAgaW4gbGlzdGluZ3MsIGFkZCBzb21lIGNvbnRlbnQgdG8gaXQuIFJhdyBzb3VyY2VzIChkaXNrLCBiYWNrYmxhemUpIERPIGxpc3RcbiAgICAgKiB0aGVpciBlbXB0eSBmaWxlcyAtIHRoYXQgaXMgaG93IHNjYW5zIGxlYXJuIG9mIGRlbGV0aW9ucyAtIGJ1dCBub3RoaW5nIGJ1aWx0IG9uIHRoZSBpbmRleFxuICAgICAqIGV2ZXIgc3VyZmFjZXMgdGhlbS5cbiAgICAgKi9cbiAgICBmaW5kKHByZWZpeDogc3RyaW5nLCBjb25maWc/OiBGaW5kQ29uZmlnKTogUHJvbWlzZTxzdHJpbmdbXT47XG4gICAgLyoqIFNlZSBmaW5kIGZvciB0aGUgZW1wdHktZmlsZSAodG9tYnN0b25lKSBydWxlLiAqL1xuICAgIGZpbmRJbmZvKHByZWZpeDogc3RyaW5nLCBjb25maWc/OiBGaW5kQ29uZmlnKTogUHJvbWlzZTxBcmNoaXZlRmlsZUluZm9bXT47XG4gICAgLyoqIE9ubHkgd29ya3MgZm9yIHB1YmxpYyBidWNrZXRzIChwcml2YXRlIGJ1Y2tldHMgYXJlIEFQSS1hY2Nlc3Mgb25seSkuICovXG4gICAgZ2V0VVJMKHBhdGg6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPjtcbiAgICAvKiogVGhlIGJ1Y2tldCdzIGNvbmZpZ3VyYXRpb24sIHdoaWNoIHRlbGxzIHdoZXRoZXIgdGhlIG9wdGlvbmFsIGZ1bmN0aW9ucyBhcmUgc3VwcG9ydGVkLiAqL1xuICAgIGdldENvbmZpZygpOiBQcm9taXNlPEFyY2hpdmVzQ29uZmlnPjtcbiAgICAvKipcbiAgICAgKiBBbGwgZmlsZXMgY2hhbmdlZCBhZnRlciBjb25maWcudGltZSwgb3B0aW9uYWxseSByZXN0cmljdGVkIHRvIGtleXMgcm91dGluZyBpbnRvIG9uZSBvZlxuICAgICAqIGNvbmZpZy5yb3V0ZXMgKHVzZWQgYnkgc2Nhbm5pbmcsIHNvIHBhcnRpYWxseS1vdmVybGFwcGluZyBzaGFyZHMgb25seSByZWNlaXZlIHRoZWlyIHNsaWNlKS5cbiAgICAgKiBXaGVuIGdldENvbmZpZygpLnN1cHBvcnRzQ2hhbmdlc0FmdGVyLCB0aGlzIGlzIGJhY2tlZCBieSBhbiBpbmRleCAoZmFzdCwgYW5kIGRlbGV0aW9ucyBBUkVcbiAgICAgKiByZXBvcnRlZCwgYXMgc2l6ZS0wIHRvbWJzdG9uZSBlbnRyaWVzKS4gRXZlcnkgb3RoZXIgYmFja2VuZCBlbXVsYXRlcyBpdDogYSBmdWxsIGZpbmRJbmZvXG4gICAgICogbGlzdGluZyBmaWx0ZXJlZCBpbiBtZW1vcnkgLSBjb3JyZWN0LCBidXQgbm8gY2hlYXBlciB0aGFuIHRoZSBsaXN0aW5nIGl0c2VsZi5cbiAgICAgKi9cbiAgICBnZXRDaGFuZ2VzQWZ0ZXIyKGNvbmZpZzogQ2hhbmdlc0FmdGVyQ29uZmlnKTogUHJvbWlzZTxBcmNoaXZlRmlsZUluZm9bXT47XG4gICAgLyoqIFN5bmNocm9uaXphdGlvbiBpbnRyb3NwZWN0aW9uLCBmb3IgYmFja2VuZHMgdGhhdCBzeW5jaHJvbml6ZSBmcm9tIHNvdXJjZXMgKHNlZSBCbG9iU3RvcmUpLiAqL1xuICAgIGdldFN5bmNTdGF0dXM/KCk6IFByb21pc2U8QXJjaGl2ZXNTeW5jU3RhdHVzPjtcbn1cbiJdfQ==
96
+ /* _JS_SOURCE_HASH = "1932addd6bcb7684ac2a8f2c46c4862b2afd1f90b96e548f9c03f8f97958f207"; */
@@ -141,7 +141,7 @@ export declare class RawDiskStore implements IBucketStore {
141
141
  export type BlobSourceSpec = {
142
142
  identity: string;
143
143
  url: string;
144
- validWindow: [number, number];
144
+ validWindows: [number, number][];
145
145
  route?: [number, number];
146
146
  noFullSync?: boolean;
147
147
  intermediate?: boolean;
@@ -296,6 +296,7 @@ export declare class BlobStore implements IBucketStore {
296
296
  private setInternal;
297
297
  private cacheRead;
298
298
  private setOrDelete;
299
+ private baseWriteWindowEnd;
299
300
  private getWritableSources;
300
301
  private writeToSources;
301
302
  private getDiskSource;
@@ -5,7 +5,7 @@ import { timeInMinute, sort, promiseObj } from "socket-function/src/misc";
5
5
  import { formatNumber, formatTime } from "socket-function/src/formatting/format";
6
6
  import {
7
7
  IArchives, ArchiveFileInfo, ArchivesSource, ArchivesSyncStatus, ChangesAfterConfig, FindConfig, HostedConfig, SourceConfig, assertValidLastModified,
8
- windowAcceptsWrites, SyncActivity, FULL_ROUTE, STORAGE_WRONG_VALID_WINDOW, STORAGE_WRONG_ROUTE, copyArchiveFile,
8
+ windowAcceptsWrites, windowsAcceptWrites, SyncActivity, FULL_ROUTE, STORAGE_WRONG_VALID_WINDOW, STORAGE_WRONG_ROUTE, copyArchiveFile,
9
9
  } from "../IArchives";
10
10
  import { ArchivesDisk, applyFindInfoShape } from "../ArchivesDisk";
11
11
  import { ArchivesBackblaze } from "../backblaze";
@@ -166,7 +166,7 @@ export type BlobSourceSpec = {
166
166
  identity: string;
167
167
  // See ArchivesSource.url
168
168
  url: string;
169
- validWindow: [number, number];
169
+ validWindows: [number, number][];
170
170
  route?: [number, number];
171
171
  noFullSync?: boolean;
172
172
  // See ArchivesSource.intermediate
@@ -470,7 +470,7 @@ export class BlobStore implements IBucketStore {
470
470
  indexSize: this.mem.size,
471
471
  sources: this.sources.map((x, i) => ({
472
472
  debugName: x.source.getDebugName(),
473
- validWindow: x.validWindow,
473
+ validWindows: x.validWindows,
474
474
  route: x.route,
475
475
  noFullSync: x.noFullSync,
476
476
  supportsChangesAfter: this.sourceStates[i].supportsChangesAfter,
@@ -530,14 +530,14 @@ export class BlobStore implements IBucketStore {
530
530
  if (entries) {
531
531
  this.entries = entries;
532
532
  }
533
- let setWindow = (i: number, window: [number, number]) => {
534
- let old = this.sources[i].validWindow;
535
- if (old[0] === window[0] && old[1] === window[1]) return;
536
- console.log(`Valid window changed for ${this.sources[i].source.getDebugName()} (store ${this.folder}): [${old.join(", ")}] -> [${window.join(", ")}]`);
537
- this.sources[i].validWindow = window;
533
+ let setWindows = (i: number, windows: [number, number][]) => {
534
+ let old = this.sources[i].validWindows;
535
+ if (JSON.stringify(old) === JSON.stringify(windows)) return;
536
+ console.log(`Valid windows changed for ${this.sources[i].source.getDebugName()} (store ${this.folder}): ${JSON.stringify(old)} -> ${JSON.stringify(windows)}`);
537
+ this.sources[i].validWindows = windows;
538
538
  };
539
- setWindow(0, specs[0].validWindow);
540
- // Live slots pair with specs by identity, in order (the same endpoint can appear several times, e.g. one entry per window)
539
+ setWindows(0, specs[0].validWindows);
540
+ // Live slots pair with specs by identity. Each endpoint is now ONE spec carrying all its windows, so this is a 1:1 pairing; any leftover duplicate slots from before (an endpoint that used to be split into several slots) go unmatched below and are collapsed away.
541
541
  let liveByIdentity = new Map<string, number[]>();
542
542
  let originalLength = this.sources.length;
543
543
  for (let i = 1; i < originalLength; i++) {
@@ -556,7 +556,7 @@ export class BlobStore implements IBucketStore {
556
556
  let slot = liveByIdentity.get(spec.identity)?.shift();
557
557
  if (slot !== undefined) {
558
558
  matched.add(slot);
559
- setWindow(slot, spec.validWindow);
559
+ setWindows(slot, spec.validWindows);
560
560
  let existing = this.sources[slot];
561
561
  if (JSON.stringify(existing.route) !== JSON.stringify(spec.route)) {
562
562
  console.log(`Route changed for ${existing.source.getDebugName()} (store ${this.folder}): ${JSON.stringify(existing.route)} -> ${JSON.stringify(spec.route)}`);
@@ -567,7 +567,7 @@ export class BlobStore implements IBucketStore {
567
567
  continue;
568
568
  }
569
569
  let source = spec.create();
570
- this.sources.push({ source, url: spec.url, validWindow: spec.validWindow, route: spec.route, noFullSync: spec.noFullSync, intermediate: spec.intermediate, sourceConfig: spec.sourceConfig, identity: spec.identity });
570
+ this.sources.push({ source, url: spec.url, validWindows: spec.validWindows, route: spec.route, noFullSync: spec.noFullSync, intermediate: spec.intermediate, sourceConfig: spec.sourceConfig, identity: spec.identity });
571
571
  this.sourceStates.push(newSourceState());
572
572
  this.sourceFileCounts.push(0);
573
573
  this.sourceByteCounts.push(0);
@@ -580,7 +580,7 @@ export class BlobStore implements IBucketStore {
580
580
  if (!this.isLive(i) || matched.has(i)) continue;
581
581
  this.removeSource(i);
582
582
  }
583
- let deadline = this.sources[0].validWindow[1] - WINDOW_END_FLUSH_MARGIN;
583
+ let deadline = this.baseWriteWindowEnd() - WINDOW_END_FLUSH_MARGIN;
584
584
  let recapped = 0;
585
585
  for (let entry of this.overlay.values()) {
586
586
  if (entry.fastFlushAt <= deadline && entry.slowFlushAt <= deadline) continue;
@@ -921,10 +921,10 @@ export class BlobStore implements IBucketStore {
921
921
  }
922
922
  }
923
923
 
924
- // An intermediate is a deploy switchover's temporary alternate port: once its window is past, the port is gone for good, so scanning it (or retrying a failed scan) can never succeed - it would just log errors forever
924
+ // An intermediate is a deploy switchover's temporary alternate port: once its window is past, the port is gone for good, so scanning it (or retrying a failed scan) can never succeed - it would just log errors forever. (Dead only once EVERY window has ended - an intermediate normally has just one.)
925
925
  private isDeadIntermediate(sourceIndex: number): boolean {
926
- let { intermediate, validWindow } = this.sources[sourceIndex];
927
- return !!intermediate && validWindow[1] <= Date.now();
926
+ let { intermediate, validWindows } = this.sources[sourceIndex];
927
+ return !!intermediate && validWindows.every(w => w[1] <= Date.now());
928
928
  }
929
929
 
930
930
  // Full metadata scan (size, writeTime, path) of one source, applied to the index. Returns the source's listing (path -> write time), which reconcileSource uses for the push direction.
@@ -987,9 +987,9 @@ export class BlobStore implements IBucketStore {
987
987
 
988
988
  // The push direction of synchronization: everything we know that the source is missing (or holds an older copy of) is written to it — including deletions, as tombstone writes. This is what heals a source whose background writes failed (e.g. it was down): the next scan sees what's missing and re-sends it. A failing file is skipped, not fatal (immutable targets are handled by forceSetImmutable, and one unreadable value must not stop the rest of the pass) - only a run of consecutive failures (the source itself is down) aborts until the next scan cycle.
989
989
  private async reconcileSource(sourceIndex: number, listing: Map<string, number>): Promise<void> {
990
- let { source, validWindow, route } = this.sources[sourceIndex];
990
+ let { source, validWindows, route } = this.sources[sourceIndex];
991
991
  let state = this.sourceStates[sourceIndex];
992
- let acceptsWrites = windowAcceptsWrites(validWindow);
992
+ let acceptsWrites = windowsAcceptWrites(validWindows);
993
993
  let targetSourcesListIndex = this.sourcesListIndexOfSlot(sourceIndex);
994
994
  let pushed = 0;
995
995
  let failed = 0;
@@ -1253,7 +1253,7 @@ export class BlobStore implements IBucketStore {
1253
1253
  writeDelay = DEFAULT_FAST_WRITE_DELAY;
1254
1254
  }
1255
1255
  // The delay never extends past our own valid window's end (minus the margin, so the writes are on disk before the next window's source takes over - a deploy switchover is just this too, since its remap ends our window). Past that point fast writes write through immediately.
1256
- let deadline = this.sources[0].validWindow[1] - WINDOW_END_FLUSH_MARGIN;
1256
+ let deadline = this.baseWriteWindowEnd() - WINDOW_END_FLUSH_MARGIN;
1257
1257
  if (writeDelay > 0 && Date.now() < deadline) {
1258
1258
  // Own disk + our own storage servers (type-"remote") flush within MAX_REMOTE_FAST_BUFFER; the non-"remote" sources (backblaze) wait the full writeDelay
1259
1259
  let fastFlushAt = Math.min(Date.now() + Math.min(writeDelay, MAX_REMOTE_FAST_BUFFER), deadline);
@@ -1266,11 +1266,21 @@ export class BlobStore implements IBucketStore {
1266
1266
  await this.writeToSources(key, data, writeTime);
1267
1267
  }
1268
1268
 
1269
+ // The end of our own (base disk) write window that CONTAINS now - the deadline fast writes must flush before, so the next window's source has the data on handoff. The LATEST end among covering windows (overlapping windows hand off at the last one). No window contains now (an inert store, or a moment between our windows) -> 0, i.e. flush through immediately.
1270
+ private baseWriteWindowEnd(): number {
1271
+ let now = Date.now();
1272
+ let end = 0;
1273
+ for (let w of this.sources[0].validWindows) {
1274
+ if (w[0] <= now && now < w[1]) end = Math.max(end, w[1]);
1275
+ }
1276
+ return end;
1277
+ }
1278
+
1269
1279
  private getWritableSources(config?: { ignoreWindow?: boolean }): number[] {
1270
1280
  let writable: number[] = [];
1271
1281
  for (let i = 0; i < this.sources.length; i++) {
1272
1282
  if (!this.isLive(i)) continue;
1273
- if (!config?.ignoreWindow && !windowAcceptsWrites(this.sources[i].validWindow)) continue;
1283
+ if (!config?.ignoreWindow && !windowsAcceptWrites(this.sources[i].validWindows)) continue;
1274
1284
  writable.push(i);
1275
1285
  }
1276
1286
  return writable;
@@ -1406,7 +1416,7 @@ export class BlobStore implements IBucketStore {
1406
1416
  for (let i = 0; i < this.sources.length; i++) {
1407
1417
  if (!this.isLive(i)) continue;
1408
1418
  let sourceEntry = this.sources[i];
1409
- if (!windowAcceptsWrites(sourceEntry.validWindow)) continue;
1419
+ if (!windowsAcceptWrites(sourceEntry.validWindows)) continue;
1410
1420
  let source = sourceEntry.source;
1411
1421
  if (!(source instanceof ArchivesBackblaze)) continue;
1412
1422
  void source.del(key).catch((e: Error) => {