sliftutils 1.7.116 → 1.7.118

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
@@ -2166,7 +2166,7 @@ declare module "sliftutils/storage/IArchives" {
2166
2166
  };
2167
2167
  /** Read ONLY from the primary source - the one writes would target - instead of falling back across the redundant sources. Use this when you want your reads and writes to be somewhat atomic: there will still be issues with the round trip, but without it you could talk to a completely different node and get a much older value. Most reads aren't followed by a write though, so for most cases it's better to get a value than to have to wait (or even throw) when the primary node is not available. */
2168
2168
  noFallbacks?: boolean;
2169
- /** Store-to-store call: the serving node answers purely from its own disk, completely short-circuiting its index holders - chasing its own remote holders while answering another store is how infinite get loops between stores form (A asks B, B's index points back at A, ...). No window or route checks on reads: if the bytes are on its disk, the caller may have them. */
2169
+ /** Store-to-store call: the serving node never consults its OTHER sources - chasing its own remote holders while answering another store is how infinite get loops between stores form (A asks B, B's index points back at A, ...). That is the flag's ENTIRE meaning: no fallbacks, nothing else. The read is otherwise fully correct - the node's index still gates it (a key its index says is deleted answers as deleted, never as the history bytes still sitting on its disk). No window or route checks on reads. */
2170
2170
  internal?: boolean;
2171
2171
  /** Also return size-0 results (tombstones - an empty file IS a missing file) instead of treating them as absent. Off by default, matching getInfo's flag of the same name. Synchronization passes this so a DELETED file (with its write time) is distinguishable from a file that never existed. */
2172
2172
  includeTombstones?: boolean;
@@ -2184,6 +2184,8 @@ declare module "sliftutils/storage/IArchives" {
2184
2184
  includeMarked?: boolean;
2185
2185
  /** Listings normally come ONLY from the authoritative sources (the same nodes writes go to - read-your-writes). With fallbacks, a failing shard's routes are covered by the next source holding them (e.g. a wide read replica) instead of the call failing - high availability at the cost of possibly missing just-written data. Single-source archives ignore the flag. */
2186
2186
  fallbacks?: boolean;
2187
+ /** Store-to-store listing: only entries whose bytes the node ITSELF holds - never entries its index redirects to its own other sources. A peer reads with GetConfig.internal (which never chases those redirects), so listing a redirect would just make the peer flag the file missing, purge it, re-list it, and loop forever; the peer hears about such files from the source actually holding them instead. */
2188
+ internal?: boolean;
2187
2189
  };
2188
2190
  export type DelConfig = {
2189
2191
  /** Stamps the deletion (its tombstone) with this write time instead of now. Synchronization passes the ORIGINAL deletion time, so deletion ordering survives propagation exactly like any other write's ordering. */
@@ -2211,6 +2213,8 @@ declare module "sliftutils/storage/IArchives" {
2211
2213
  time: number;
2212
2214
  /** Only keys routing into one of these [start, end) ranges. Only scanning passes this - it lets a store syncing a partial shard ask for just its slice. */
2213
2215
  routes?: [number, number][];
2216
+ /** See FindConfig.internal - the change feed is a listing too, and redirect entries fail a peer's internal reads the same way. Deletions are always reported (they are index-only, there are no bytes to hold). */
2217
+ internal?: boolean;
2214
2218
  };
2215
2219
  export type SetConfig = {
2216
2220
  /** The write time to stamp (see IArchives.set). ROUNDED to whole milliseconds by every implementation - the disk can't store fractional milliseconds anyway (utimes round-trips whole ms), so a fractional stamp could never be reproduced by propagation and would compare "newer" than its own copies forever. Rounded rather than floored because utimes goes through a seconds double and can read back a hair below the stamped millisecond (see ArchivesDisk.get2). */
@@ -3715,7 +3719,7 @@ declare module "sliftutils/storage/remoteStorage/blobStore" {
3715
3719
  private assertFreshWriteTarget;
3716
3720
  private assertMutable;
3717
3721
  private assertInternalWriteAccepted;
3718
- /** Internal (store-to-store) read: purely the local disk, completely short-circuiting the index and holder resolution - the caller is another store, and chasing OUR remote holders while answering it is how infinite get loops between stores form. No window or route checks: if the bytes are on our disk, the caller may have them. Note this reads the disk past any write delay, so a fast write still buffered in memory is invisible here; the caller re-finds it once it flushes. */
3722
+ /** Internal (store-to-store) read: never goes to OTHER sources - the caller is another store, and chasing OUR remote holders while answering it is how infinite get loops between stores form - but the INDEX still gates, because it is the source of truth: a marked deletion keeps its bytes on disk as history (see writeToSources), so the disk alone would happily serve a DELETED file as live. Index says live -> the disk provides the bytes (past any write delay, so a fast write still buffered in memory is invisible here; the caller re-finds it once it flushes). Index says deleted -> the tombstone is the answer, never the disk. No window or route checks. */
3719
3723
  private getInternal2;
3720
3724
  /** Internal (store-to-store) write: the local disk plus our index, with NO downstream fan-out - the pushing store owns propagation, and fanning its pushes back out is how write loops between stores form. Only-take-latest still applies here. */
3721
3725
  private setInternal;
@@ -4295,6 +4299,8 @@ declare module "sliftutils/storage/remoteStorage/sourceWrapper" {
4295
4299
  seedLatency(ms: number): void;
4296
4300
  /** Median of the recent pings (API or URL-form, whichever this source measures), plus DISCONNECTED_LATENCY_PENALTY while the source is disconnected - so a down source still sorts and can still be picked, just after every connected one. Sources with no measurements yet sort last (Infinity), except our own in-process server, which is the best possible target (0). */
4297
4301
  getLatency(): number;
4302
+ /** writeBlocked from missing backblaze credentials is re-checked on every write attempt: the secret load can fail TRANSIENTLY (early startup, a file-read hiccup), and one failed load must never permanently stop this process from writing to the bucket. The other writeBlocked reasons (read-only mode, browsers) are static properties of the process, so there is nothing to re-check. */
4303
+ recheckWriteBlocked(): Promise<void>;
4298
4304
  /** Writes always go through the API, so a permission error throws to the caller on every write (and access granted in the meantime is picked up automatically). */
4299
4305
  write<T>(run: (archives: IArchives) => Promise<T>): Promise<T>;
4300
4306
  dispose(): void;
@@ -4484,6 +4490,7 @@ declare module "sliftutils/storage/remoteStorage/storageController" {
4484
4490
  sourceConfig: SourceConfig;
4485
4491
  time: number;
4486
4492
  routes?: [number, number][];
4493
+ internal?: boolean;
4487
4494
  }) => Promise<ArchiveFileInfo[]>;
4488
4495
  getArchivesConfig: (config: {
4489
4496
  account: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sliftutils",
3
- "version": "1.7.116",
3
+ "version": "1.7.118",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "files": [
@@ -57,7 +57,7 @@
57
57
  "node-forge": "https://github.com/sliftist/forge#e618181b469b07bdc70b968b0391beb8ef5fecd6",
58
58
  "preact-old-types": "^10.28.1",
59
59
  "shell-quote": "^1.8.3",
60
- "socket-function": "^1.2.32",
60
+ "socket-function": "^1.2.33",
61
61
  "typenode": "^6.6.1",
62
62
  "typesafecss": "*",
63
63
  "ws": "^8.18.3",
package/spec.txt CHANGED
@@ -1,11 +1,10 @@
1
- Refactor
2
1
 
3
- createArchives => storageController => storageServerState => BlobStore
4
-
5
- So create Archives has to decide who we're going to talk to, and then Storage Controller, it just acts like adds security and stuff. and then it gets into load it bucket, and then load it bucket. It then decides what back-end store we're talking to, and the back-end store, it might talk to multiple sources.
6
- So there's which server we're going to talk to, which bucket on the server it maps to once we get there, and then there's which back-end stores that we talk to. So I guess it's fine.
7
2
 
3
+ test
4
+ --internal
5
+ --selcert
8
6
 
7
+ with a test.ts script
9
8
 
10
9
 
11
10
  TODO: Use wildcard certificates, and then expose urls which match up to the shard fraction, to 2 decimal places:
@@ -71,7 +71,7 @@ export type GetConfig = {
71
71
  };
72
72
  /** Read ONLY from the primary source - the one writes would target - instead of falling back across the redundant sources. Use this when you want your reads and writes to be somewhat atomic: there will still be issues with the round trip, but without it you could talk to a completely different node and get a much older value. Most reads aren't followed by a write though, so for most cases it's better to get a value than to have to wait (or even throw) when the primary node is not available. */
73
73
  noFallbacks?: boolean;
74
- /** Store-to-store call: the serving node answers purely from its own disk, completely short-circuiting its index holders - chasing its own remote holders while answering another store is how infinite get loops between stores form (A asks B, B's index points back at A, ...). No window or route checks on reads: if the bytes are on its disk, the caller may have them. */
74
+ /** Store-to-store call: the serving node never consults its OTHER sources - chasing its own remote holders while answering another store is how infinite get loops between stores form (A asks B, B's index points back at A, ...). That is the flag's ENTIRE meaning: no fallbacks, nothing else. The read is otherwise fully correct - the node's index still gates it (a key its index says is deleted answers as deleted, never as the history bytes still sitting on its disk). No window or route checks on reads. */
75
75
  internal?: boolean;
76
76
  /** Also return size-0 results (tombstones - an empty file IS a missing file) instead of treating them as absent. Off by default, matching getInfo's flag of the same name. Synchronization passes this so a DELETED file (with its write time) is distinguishable from a file that never existed. */
77
77
  includeTombstones?: boolean;
@@ -89,6 +89,8 @@ export type FindConfig = {
89
89
  includeMarked?: boolean;
90
90
  /** Listings normally come ONLY from the authoritative sources (the same nodes writes go to - read-your-writes). With fallbacks, a failing shard's routes are covered by the next source holding them (e.g. a wide read replica) instead of the call failing - high availability at the cost of possibly missing just-written data. Single-source archives ignore the flag. */
91
91
  fallbacks?: boolean;
92
+ /** Store-to-store listing: only entries whose bytes the node ITSELF holds - never entries its index redirects to its own other sources. A peer reads with GetConfig.internal (which never chases those redirects), so listing a redirect would just make the peer flag the file missing, purge it, re-list it, and loop forever; the peer hears about such files from the source actually holding them instead. */
93
+ internal?: boolean;
92
94
  };
93
95
  export type DelConfig = {
94
96
  /** Stamps the deletion (its tombstone) with this write time instead of now. Synchronization passes the ORIGINAL deletion time, so deletion ordering survives propagation exactly like any other write's ordering. */
@@ -116,6 +118,8 @@ export type ChangesAfterConfig = {
116
118
  time: number;
117
119
  /** Only keys routing into one of these [start, end) ranges. Only scanning passes this - it lets a store syncing a partial shard ask for just its slice. */
118
120
  routes?: [number, number][];
121
+ /** See FindConfig.internal - the change feed is a listing too, and redirect entries fail a peer's internal reads the same way. Deletions are always reported (they are index-only, there are no bytes to hold). */
122
+ internal?: boolean;
119
123
  };
120
124
  export type SetConfig = {
121
125
  /** The write time to stamp (see IArchives.set). ROUNDED to whole milliseconds by every implementation - the disk can't store fractional milliseconds anyway (utimes round-trips whole ms), so a fractional stamp could never be reproduced by propagation and would compare "newer" than its own copies forever. Rounded rather than floored because utimes goes through a seconds double and can read back a hair below the stamped millisecond (see ArchivesDisk.get2). */
@@ -106,7 +106,7 @@ export type GetConfig = {
106
106
  range?: { start: number; end: number };
107
107
  /** Read ONLY from the primary source - the one writes would target - instead of falling back across the redundant sources. Use this when you want your reads and writes to be somewhat atomic: there will still be issues with the round trip, but without it you could talk to a completely different node and get a much older value. Most reads aren't followed by a write though, so for most cases it's better to get a value than to have to wait (or even throw) when the primary node is not available. */
108
108
  noFallbacks?: boolean;
109
- /** Store-to-store call: the serving node answers purely from its own disk, completely short-circuiting its index holders - chasing its own remote holders while answering another store is how infinite get loops between stores form (A asks B, B's index points back at A, ...). No window or route checks on reads: if the bytes are on its disk, the caller may have them. */
109
+ /** Store-to-store call: the serving node never consults its OTHER sources - chasing its own remote holders while answering another store is how infinite get loops between stores form (A asks B, B's index points back at A, ...). That is the flag's ENTIRE meaning: no fallbacks, nothing else. The read is otherwise fully correct - the node's index still gates it (a key its index says is deleted answers as deleted, never as the history bytes still sitting on its disk). No window or route checks on reads. */
110
110
  internal?: boolean;
111
111
  /** Also return size-0 results (tombstones - an empty file IS a missing file) instead of treating them as absent. Off by default, matching getInfo's flag of the same name. Synchronization passes this so a DELETED file (with its write time) is distinguishable from a file that never existed. */
112
112
  includeTombstones?: boolean;
@@ -125,6 +125,8 @@ export type FindConfig = {
125
125
  includeMarked?: boolean;
126
126
  /** Listings normally come ONLY from the authoritative sources (the same nodes writes go to - read-your-writes). With fallbacks, a failing shard's routes are covered by the next source holding them (e.g. a wide read replica) instead of the call failing - high availability at the cost of possibly missing just-written data. Single-source archives ignore the flag. */
127
127
  fallbacks?: boolean;
128
+ /** Store-to-store listing: only entries whose bytes the node ITSELF holds - never entries its index redirects to its own other sources. A peer reads with GetConfig.internal (which never chases those redirects), so listing a redirect would just make the peer flag the file missing, purge it, re-list it, and loop forever; the peer hears about such files from the source actually holding them instead. */
129
+ internal?: boolean;
128
130
  };
129
131
 
130
132
  export type DelConfig = {
@@ -155,6 +157,8 @@ export type ChangesAfterConfig = {
155
157
  time: number;
156
158
  /** Only keys routing into one of these [start, end) ranges. Only scanning passes this - it lets a store syncing a partial shard ask for just its slice. */
157
159
  routes?: [number, number][];
160
+ /** See FindConfig.internal - the change feed is a listing too, and redirect entries fail a peer's internal reads the same way. Deletions are always reported (they are index-only, there are no bytes to hold). */
161
+ internal?: boolean;
158
162
  };
159
163
 
160
164
  export type SetConfig = {
@@ -58,5 +58,5 @@ exports.bufferChunkStream = bufferChunkStream;
58
58
  // Re-exported for the existing importers - the implementations (and moveArchiveFile) live in archiveHelpers.ts, beside this interface rather than in it
59
59
  var archiveHelpers_1 = require("./archiveHelpers");
60
60
  Object.defineProperty(exports, "copyArchiveFile", { enumerable: true, get: function () { return archiveHelpers_1.copyArchiveFile; } , configurable: true});
61
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiSUFyY2hpdmVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiSUFyY2hpdmVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSx3S0FBd0s7OztBQUV4SyxzSkFBc0o7QUFDekksUUFBQSx3QkFBd0IsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQUV2RCx5TEFBeUw7QUFDNUssUUFBQSxvQkFBb0IsR0FBRyxLQUFLLEdBQUcsSUFBSSxDQUFDO0FBQ2pELFNBQWdCLHVCQUF1QixDQUFDLFlBQW9CO0lBQ3hELElBQUksR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxnQ0FBd0IsQ0FBQztJQUNoRCxJQUFJLFlBQVksR0FBRyxHQUFHLEVBQUUsQ0FBQztRQUNyQixNQUFNLElBQUksS0FBSyxDQUFDLDBDQUEwQyxZQUFZLE1BQU0sR0FBRyxxQkFBcUIsQ0FBQyxDQUFDO0lBQzFHLENBQUM7QUFDTCxDQUFDO0FBTEQsMERBS0M7QUF1RlksUUFBQSxpQkFBaUIsR0FBcUIsQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUM7QUF3SWhGLHdYQUF3WDtBQUMzVyxRQUFBLDBCQUEwQixHQUFHLDRDQUE0QyxDQUFDO0FBRXZGLDhMQUE4TDtBQUNqTCxRQUFBLG1CQUFtQixHQUFHLHFDQUFxQyxDQUFDO0FBRXpFLHVXQUF1VztBQUMxVixRQUFBLHNCQUFzQixHQUFHLHdDQUF3QyxDQUFDO0FBRWxFLFFBQUEsVUFBVSxHQUFxQixDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUVuRCwyUkFBMlI7QUFDOVEsUUFBQSxjQUFjLEdBQUcsNkNBQTZDLENBQUM7QUFDNUUsb0xBQW9MO0FBQ3BMLDhKQUE4SjtBQUM5SixTQUFnQixtQkFBbUIsQ0FBQyxXQUF5QztJQUN6RSxJQUFJLENBQUMsV0FBVztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQzlCLE9BQU8sV0FBVyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztBQUN2QyxDQUFDO0FBSEQsa0RBR0M7QUFDRCxpTkFBaU47QUFDak4sU0FBZ0IsbUJBQW1CLENBQUMsWUFBZ0M7SUFDaEUsT0FBTyxZQUFZLENBQUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLENBQUM7QUFDbEQsQ0FBQztBQUZELGtEQUVDO0FBRUQsd0tBQXdLO0FBQzNKLFFBQUEsbUJBQW1CLEdBQUcsQ0FBQyxHQUFHLElBQUksR0FBRyxJQUFJLENBQUM7QUFFbkQsbVJBQW1SO0FBQ25SLFNBQWdCLGlCQUFpQixDQUFDLElBQVk7SUFDMUMsSUFBSSxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ2YsT0FBTztRQUNILFdBQVcsRUFBRSxLQUFLLElBQUksRUFBRTtZQUNwQixJQUFJLE1BQU0sSUFBSSxJQUFJLENBQUMsTUFBTTtnQkFBRSxPQUFPLFNBQVMsQ0FBQztZQUM1QyxJQUFJLEtBQUssR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxNQUFNLEdBQUcsMkJBQW1CLENBQUMsQ0FBQztZQUNoRSxNQUFNLElBQUksS0FBSyxDQUFDLE1BQU0sQ0FBQztZQUN2QixPQUFPLEtBQUssQ0FBQztRQUNqQixDQUFDO1FBQ0QsYUFBYSxFQUFFLEdBQUcsRUFBRTtZQUNoQixNQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQ2YsQ0FBQztLQUNKLENBQUM7QUFDTixDQUFDO0FBYkQsOENBYUM7QUFFRCx3SkFBd0o7QUFDeEosbURBQW1EO0FBQTFDLGlIQUFBLGVBQWUsT0FBQSIsInNvdXJjZXNDb250ZW50IjpbIi8vIFRoZSBpbXBvcnRhbnQgb3BlcmF0aW9ucyBvZiBhbiBhcmNoaXZlIGJ1Y2tldCAoZXh0cmFjdGVkIGZyb20gQXJjaGl2ZXNCYWNrYmxhemUpLCBzbyBvdGhlciBiYWNrZW5kcyAoZS5nLiBvdXIgb3duIHJlbW90ZSBzdG9yYWdlIHNlcnZlcikgY2FuIGJlIHVzZWQgaW50ZXJjaGFuZ2VhYmx5LlxuXG4vLyBBIHdyaXRlIG1heSBub3QgYmUgc3RhbXBlZCBtb3JlIHRoYW4gdGhpcyBmYXIgaW4gdGhlIGZ1dHVyZSwgb3IgY2xvY2sgc2tldyBiZXR3ZWVuIG1hY2hpbmVzIHdvdWxkIGxldCBhIGJhZCB0aW1lc3RhbXAgYmxvY2sgd3JpdGVzIGZvciBhIGxvbmcgdGltZS5cbmV4cG9ydCBjb25zdCBNQVhfTEFTVF9NT0RJRklFRF9GVVRVUkUgPSAxNSAqIDYwICogMTAwMDtcblxuLy8gSG93IGxvbmcgYnJvd3NlcnMgbWF5IGNhY2hlIGZpbGVzIGZyb20gaW1tdXRhYmxlIGJ1Y2tldHMgKHRoZSBDYWNoZS1Db250cm9sIG1heC1hZ2UpLCBzaGFyZWQgYnkgZXZlcnkgaG9zdGluZyBwYXRoIChiYWNrYmxhemUgYnVja2V0IHNldHRpbmdzIGFuZCBvdXIgb3duIHN0b3JhZ2Ugc2VydmVyJ3MgSFRUUCByb3V0ZSlcbmV4cG9ydCBjb25zdCBJTU1VVEFCTEVfQ0FDSEVfVElNRSA9IDg2NDAwICogMTAwMDtcbmV4cG9ydCBmdW5jdGlvbiBhc3NlcnRWYWxpZExhc3RNb2RpZmllZChsYXN0TW9kaWZpZWQ6IG51bWJlcik6IHZvaWQge1xuICAgIGxldCBtYXggPSBEYXRlLm5vdygpICsgTUFYX0xBU1RfTU9ESUZJRURfRlVUVVJFO1xuICAgIGlmIChsYXN0TW9kaWZpZWQgPiBtYXgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBsYXN0TW9kaWZpZWQgaXMgdG9vIGZhciBpbiB0aGUgZnV0dXJlOiAke2xhc3RNb2RpZmllZH0gPiAke21heH0gKG5vdyArIDE1IG1pbnV0ZXMpYCk7XG4gICAgfVxufVxuXG5cbmV4cG9ydCB0eXBlIFJlbW90ZUNvbmZpZyA9IHtcbiAgICAvLyBOT1RFOiBWZXJzaW9uIGlzIHVzZWQgd2hlbiB1cGRhdGluZyB0aGUgY29uZmlndXJhdGlvbi4gVGhlIG5ld2VyIHZlcnNpb24gaXMgYWx3YXlzIHRha2VuLiBBIG1pc3NpbmcgdmVyc2lvbiBjb3VudHMgYXMgdmVyc2lvbiAtMS5cbiAgICB2ZXJzaW9uPzogbnVtYmVyO1xuICAgIHNvdXJjZXM6IFJlbW90ZUNvbmZpZ0Jhc2VbXTtcbn07XG5cbi8qKlxuICAgIHN0cmluZyBhcmd1bWVudHMgd2lsbCBiZSBhIHVybCwgbG9va2luZyBsaWtlOlxuICAgICAgICBodHRwczovL3N0b3JhZ2UyLnZpZGdyaWR3ZWIuY29tOjQ0NDUvZmlsZS9leGFtcGxlYWNjb3VudC9leGFtcGxlYnVja2V0L3N0b3JhZ2Uvc3RvcmFnZXJvdXRpbmcuanNvblxuICAgICAgICBodHRwczovL2YwMDIuYmFja2JsYXplYjIuY29tL2ZpbGUvcXVlcnlzdWJ0ZXN0LWNvbS1wdWJsaWMtaW1tdXRhYmxlL3N0b3JhZ2Uvc3RvcmFnZXJvdXRpbmcuanNvblxuICAgICAgICAtIFRoZXNlIG1hcCB0byB7IHVybCB9LCB3aXRoIHRoZSB0eXBlIGluZmVycmVkIGZyb20gdGhlIHVybFxuICAgICAgICAtIEhvc3RlZCB1cmxzIGFyZSAvZmlsZS88YWNjb3VudD4vPGJ1Y2tldE5hbWU+Ly4uLiwgYmFja2JsYXplIHVybHMgYXJlIC9maWxlLzxidWNrZXROYW1lPi8uLi5cblxuICAgIE5PVEU6IElmIHdlIGRvIG5vdCBoYXZlIHJpZ2h0IGFjY2VzcyB0byB0aGVzZSwgdGhlbiBpdCBiZWNvbWVzIGEgcmVhZC1vbmx5IElBcmNoaXZlcywgd2hlcmUgd2Ugc29sZWx5IHJlYWQgdXNpbmcgdGhlIHVybCBmb3JtICh3aGljaCBtaWdodCB0aHJvdyBkdWUgdG8gbm90IGhhdmluZyBhY2Nlc3MgYXMgd2VsbCkuIFVOTEVTUyBPdXIgY29uZmlndXJhdGlvbiBleHBsaWNpdGx5IGhhcyBwdWJsaWM6IGZhbHNlLCBpbiB3aGljaCBjYXNlLCB3ZSBkb24ndCBldmVuIGhpdCB0aGUgVVJMIGFuZCB3ZSB0aHJvdyBvbiBhY2Nlc3MuXG5cbiAgICBOT1RFOiBJZiB3ZSdyZSBpbiB0aGUgYnJvd3Nlciwgd2Ugc2hvdWxkIGFsbG93IGRvd25sb2FkaW5nIHRoZSBmaWxlcyB2aWEgdGhlIFVSTCBmb3JtIChpZiBpdCdzIGEgcHVibGljIGJ1Y2tldCksIGhvd2V2ZXIsIHdlIHdvbid0IGFsbG93IHdyaXRpbmcsIGJlY2F1c2UgdGhlaXIgc2VydmVycyBkbyBub3QgYWxsb3cgc2VjdXJlIGJyb3dzZXIgd3JpdGVzLlxuKi9cbmV4cG9ydCB0eXBlIFJlbW90ZUNvbmZpZ0Jhc2UgPSBzdHJpbmcgfCBTb3VyY2VDb25maWc7XG5cbi8qKiBPbmUgY29uZmlndXJlZCBzb3VyY2UgaW4gYSByb3V0aW5nIGNvbmZpZzogYSBob3N0ZWQgKG91ciBzdG9yYWdlIHNlcnZlcikgb3IgYmFja2JsYXplIGVudHJ5LiBSZXF1ZXN0cyBjYXJyeSB0aGUgZXhhY3QgU291cmNlQ29uZmlnIHRoZXkgc2VsZWN0ZWQsIGFuZCB0aGUgc2VydmVyIG1hdGNoZXMgaXQgYWdhaW5zdCBpdHMgb3duIGVudHJpZXMgdG8gcGljayB0aGUgYmFja2luZyBzdG9yZS4gKi9cbmV4cG9ydCB0eXBlIFNvdXJjZUNvbmZpZyA9IEhvc3RlZENvbmZpZyB8IEJhY2tibGF6ZUNvbmZpZztcblxuZXhwb3J0IHR5cGUgQ29tbW9uQ29uZmlnID0ge1xuICAgIC8qKlxuICAgICAqIFRoZSBzdG9yYWdlIHRoaXMgZW50cnkgbmFtZXMsIGFzIG9wcG9zZWQgdG8gdGhlIHJ1bGVzIGZvciB1c2luZyBpdC4gRXZlcnkgZW50cnkgd2l0aCB0aGUgc2FtZVxuICAgICAqIG5hbWUgKGZvciB0aGUgc2FtZSBhY2NvdW50IGFuZCBidWNrZXQpIElTIHRoZSBzYW1lIHN0b3JhZ2U6IG9uZSBmb2xkZXIgb24gdGhlIHNlcnZlciwgb25lXG4gICAgICogc3RvcmUsIG9uZSBpbmRleCAtIGhvd2V2ZXIgbWFueSBlbnRyaWVzIHRoZXJlIGFyZSBhbmQgd2hhdGV2ZXIgdGhlaXIgd2luZG93cyBhbmQgcm91dGVzIHNheS5cbiAgICAgKiBFdmVyeXRoaW5nIGFib3V0IFdIRU4gYW5kIFdISUNIIEtFWVMgKHZhbGlkV2luZG93LCByb3V0ZSkgaXMgcG9saWN5IGxheWVyZWQgb24gdG9wIG9mIGl0LCBhbmRcbiAgICAgKiBjaGFuZ2luZyB0aGF0IHBvbGljeSBuZXZlciBtb3ZlcyBkYXRhLlxuICAgICAqXG4gICAgICogTGV0dGVycywgbnVtYmVycywgdW5kZXJzY29yZSwgZGFzaCBhbmQgcGVyaW9kcywgdXAgdG8gNjQgY2hhcmFjdGVycyAtIHNvIGEgaG9zdCBvciBhIHZlcnNpb25cbiAgICAgKiBjYW4gYmUgdXNlZCBhcy1pcy4gSXQgaXMgdGhlIGZvbGRlciBuYW1lLCBzbyBpdCBtdXN0IHN0YXkgdW5pcXVlIGFuZCBtdXN0IG5ldmVyIGJlIHJldXNlZCBmb3JcbiAgICAgKiBkaWZmZXJlbnQgc3RvcmFnZTpcbiAgICAgKiBwb2ludGluZyB0d28gdW5yZWxhdGVkIGVudHJpZXMgYXQgb25lIG5hbWUgbWVyZ2VzIHRoZWlyIGRhdGEsIGFuZCByZS11c2luZyBhIHJldGlyZWQgbmFtZVxuICAgICAqIGhhbmRzIHRoZSBuZXcgZW50cnkgdGhlIHJldGlyZWQgb25lJ3MgZmlsZXMuIERlY2lkaW5nIHRoYXQgaXMgdGhlIGRldmVsb3BlcidzIGpvYiAtIHRoZSBzZXJ2ZXJcbiAgICAgKiBvbmx5IGV2ZXIgZG9lcyB3aGF0IHRoZSBuYW1lIHNheXMuXG4gICAgICovXG4gICAgbmFtZTogc3RyaW5nO1xuICAgIC8qKiBCeSBkZWZhdWx0IGEgc2VydmVyIGhvc3RpbmcgdGhpcyBidWNrZXQgZWFnZXJseSBjb3BpZXMgdGhpcyBzb3VyY2UncyBmdWxsIGNvbnRlbnRzIG9udG8gaXRzIG93biBkaXNrIChvbiB0b3Agb2YgdGhlIGxhenkgcmVhZC10aHJvdWdoIGNhY2hpbmcpLiBTZXQgdGhpcyB0byBiZSBhIGZyb250IGVuZCBmb3IgYSB2ZXJ5IGxhcmdlIGRhdGFiYXNlIHdpdGhvdXQgY29weWluZyB0aGUgZnVsbCBkYXRhYmFzZSAtIHJlYWRzIHN0aWxsIGRvd24tY2FjaGUgaW5kaXZpZHVhbCBmaWxlcyBvbiBkZW1hbmQuICovXG4gICAgbm9GdWxsU3luYz86IGJvb2xlYW47XG4gICAgLyoqIEJ5dGVzIG9mIHJlYWQtY2FjaGUgdGhpcyBzZXJ2ZXIncyBkaXNrIG1heSBob2xkOyBsZWFzdC1yZWNlbnRseS11c2VkIGZpbGVzIGFyZSBkZWxldGVkIGZyb20gZGlzayB0byBzdGF5IHVuZGVyIGl0IChvbmx5IGV2ZXIgd2hlbiBhbm90aGVyIHNvdXJjZSB2ZXJpZmlhYmx5IGhvbGRzIHRoZSBmaWxlIC0gdGhlIG9ubHkgY29weSBpcyBuZXZlciBkZWxldGVkKS4gUmVxdWlyZXMgbm9GdWxsU3luYyAoYSBmdWxsIGNvcHkgY2FuJ3QgYmUgYm91bmRlZCkuICovXG4gICAgcmVhZGVyRGlza0xpbWl0PzogbnVtYmVyO1xuICAgIC8qKiBUaGUgd3JpdGUgdGltZXMgKFtzdGFydE1zLCBlbmRNc10pIHRoaXMgc291cmNlIGlzIHZhbGlkIGZvciAoc2VlIEFyY2hpdmVzU291cmNlLnZhbGlkV2luZG93IGZvciB0aGUgc3luY2hyb25pemF0aW9uIHNlbWFudGljcykuIFJlcXVpcmVkIG9uIG9iamVjdCBjb25maWdzOiBjb25maWd1cmF0aW9uIGNoYW5nZXMgbXVzdCBiZSBTQ0hFRFVMRUQgKGEgbmV3IHNvdXJjZSBiZWNvbWVzIHZhbGlkIGF0IGEgZnV0dXJlIHRpbWUgd2hpbGUgdGhlIG9sZCBvbmUncyB3aW5kb3cgZW5kcyksIG5vdCBmbGlwcGVkIGluc3RhbnRseS4gUGxhaW4gVVJMLXN0cmluZyBzb3VyY2VzIGRlZmF1bHQgdG8gRlVMTF9WQUxJRF9XSU5ET1cgLSBvbmNlIHlvdSdyZSB3cml0aW5nIG9iamVjdCBjb25maWdzLCB5b3UncmUgZG9pbmcgc29tZXRoaW5nIGNvbXBsaWNhdGVkIGVub3VnaCB0byB0aGluayBhYm91dCB3aGVuIHRoaW5ncyBjaGFuZ2UuICovXG4gICAgdmFsaWRXaW5kb3c6IFtudW1iZXIsIG51bWJlcl07XG4gICAgLyoqIFNoYXJkaW5nOiB0aGUgZnJhY3Rpb24gb2YgdGhlIGtleSBzcGFjZSB0aGlzIHNvdXJjZSBoYW5kbGVzLCBhcyBbc3RhcnQsIGVuZCkgb3ZlciBbMCwgMSkgKGtleXMgYXJlIHJvdXRlZCBieSBnZXRSb3V0ZSBpbiByZW1vdGVDb25maWcudHMpLiBEZWZhdWx0cyB0byBGVUxMX1JPVVRFICh1bnNoYXJkZWQpLiBBdCBldmVyeSBwb2ludCBpbiB0aW1lIHRoZSBzb3VyY2VzJyByb3V0ZXMgbXVzdCBmdWxseSBjb3ZlciBbMCwgMSksIG9yIHNvbWUga2V5cyBjb3VsZCBuZXZlciBiZSByZWFkLiAqL1xuICAgIHJvdXRlPzogW251bWJlciwgbnVtYmVyXTtcbiAgICAvKiogU2V0IG9uIGVudHJpZXMgaW5qZWN0ZWQgaW50byB0aGUgaW4tbWVtb3J5IGNvbmZpZyBieSBhbiBvdmVybGF5IChhIGRlcGxveSBzd2l0Y2hvdmVyJ3MgYWx0ZXJuYXRlLXBvcnQgd2luZG93KS4gTmV2ZXIgd3JpdHRlbiB0byBkaXNrOiByZXNvbHZlSW50ZXJtZWRpYXRlU291cmNlcyBzdHJpcHMgdGhlc2UgYW5kIHJlam9pbnMgdGhlIHdpbmRvd3MgYXJvdW5kIHRoZW0sIHdoaWNoIGlzIGFsc28gaG93IGEgY2xpZW50IHRlbGxzIHdoZXRoZXIgYW4gdXBkYXRlIGlzIGEgcmVhbCBjb25maWd1cmF0aW9uIGNoYW5nZSBvciBqdXN0IGFuIG92ZXJsYXkuIFRoZSBWQUxVRSBpcyB0aGUgdXJsIG9mIHRoZSBzb3VyY2UgdGhpcyBpbnRlcm1lZGlhdGUgd2FzIHNwbGl0IG91dCBvZiAoaXRzIGFsdGVybmF0ZS1wb3J0IHZpZXcpIC0gc28gYSByZXF1ZXN0IG5hbWluZyB0aGUgaW50ZXJtZWRpYXRlIHN0aWxsIHJlc29sdmVzIHRvIHRoZSBPUklHSU5BTCBzb3VyY2UsIGV2ZW4gYWZ0ZXIgdGhlIGludGVybWVkaWF0ZSByZWpvaW5zIGFuZCB0aGUgZW50cnkgaXMgZ29uZS4gKi9cbiAgICBpbnRlcm1lZGlhdGU/OiBzdHJpbmc7XG59O1xuXG5leHBvcnQgdHlwZSBIb3N0ZWRDb25maWcgPSBDb21tb25Db25maWcgJiB7XG4gICAgdHlwZTogXCJyZW1vdGVcIjtcblxuICAgIC8vIEV4OiBodHRwczovLzk5LTI1MC0xMjQtOTEucXVlcnlzdWJ0ZXN0LmNvbTo1MjMzL2ZpbGUvcm9vdC91bmlxdWVidWNrZXRuYW1lL3N0b3JhZ2Uvc3RvcmFnZXJvdXRpbmcuanNvblxuICAgIC8vIE5PVEU6IFRoZSBhY2NvdW50IGFuZCBidWNrZXQgbmFtZSBhcmUgb2J0YWluZWQgZnJvbSB0aGUgVVJMLlxuICAgIHVybDogc3RyaW5nO1xuXG4gICAgLy8gTk9URTogQXV0aGVudGljYXRpb24gaXMgaGFuZGxlZCBieSBjZXJ0LnRzLCB2aWEgaGF2aW5nIHlvdXIgbWFjaGluZSB0cnVzdGVkIHRvIGFjY2VzcyB0aGlzIGFjY291bnQuIFxuXG4gICAgcHVibGljPzogYm9vbGVhbjtcbiAgICAvLyBGYXN0IG1vZGU6IHRoZSBzZXJ2ZXIgYWNrbm93bGVkZ2VzIHdyaXRlcyBvbmNlIHRoZXkgYXJlIGluIG1lbW9yeSwgZmx1c2hpbmcgdG8gZGlzayBhZnRlciB3cml0ZURlbGF5IChkZWZhdWx0IDUgbWludXRlcykgYW5kIGNvYWxlc2Npbmcgd3JpdGVzIHRvIHRoZSBzYW1lIGZpbGUuIEEgc2VydmVyIGNyYXNoIGxvc2VzIHdyaXRlcyB0aGF0IGhhdmVuJ3QgZmx1c2hlZCB5ZXQuXG4gICAgZmFzdD86IGJvb2xlYW47XG4gICAgd3JpdGVEZWxheT86IG51bWJlcjtcbiAgICAvLyBXcml0ZXMgdG8gcGF0aHMgdGhhdCBhbHJlYWR5IGV4aXN0IGFyZSBkaXNhbGxvd2VkIChkZWxldGVzIHN0aWxsIHdvcmspLlxuICAgIGltbXV0YWJsZT86IGJvb2xlYW47XG59O1xuXG5leHBvcnQgdHlwZSBCYWNrYmxhemVDb25maWcgPSBDb21tb25Db25maWcgJiB7XG4gICAgdHlwZTogXCJiYWNrYmxhemVcIjtcbiAgICAvLyBFeDogaHR0cHM6Ly9mMDAyLmJhY2tibGF6ZWIyLmNvbS9maWxlL3F1ZXJ5c3VidGVzdC1jb20tcHVibGljLWltbXV0YWJsZS9zdG9yYWdlL3N0b3JhZ2Vyb3V0aW5nLmpzb25cbiAgICAvLyBOT1RFOiBUaGUgYnVja2V0IG5hbWUgaXMgb2J0YWluZWQgZnJvbSB0aGUgVVJMLlxuICAgIHVybDogc3RyaW5nO1xuICAgIC8vIFB1YmxpYyBidWNrZXRzIGFyZSBzZXJ2ZWQgb3ZlciBwbGFpbiBIVFRQUyBHRVRzIChnZXRVUkwpLiBQcml2YXRlIGJ1Y2tldHMgYXJlIEFQSS1hY2Nlc3Mgb25seS5cbiAgICBwdWJsaWM/OiBib29sZWFuO1xuICAgIC8vIE5PVEU6IFRoaXMgaXNuJ3QgZW5mb3JjZWQgb24gdGhlIGJhY2tibGF6ZSBsZXZlbCwgc28gdGhpcyBpcyBqdXN0IGEgY2xpZW50LXNpZGUgZ3VhcmFudGVlLiBUaGlzIGNhbiBjaGFuZ2UgaG93IHdlIGNhY2hlIGZpbGVzLlxuICAgIC8vICAtIEJhY2tibGF6ZSBkb2VzIHN1cHBvcnQgaW1tdXRhYmlsaXR5LiBIb3dldmVyLCBhcHBhcmVudGx5LCBvbmNlIHdlIGVuYWJsZSBpdCBvbiBhIGJ1Y2tldCwgd2UgY2FuJ3QgZGlzYWJsZSBpdCwgd2hpY2ggaXMgcmVhbGx5IGJhZCwgYXMgaXQgbWVhbnMgaWYgb3VyIGNvZGUgY291bGQgZXZlciBlbmFibGUgaXQgYW5kIHdlIGFjY2lkZW50YWxseSBlbmFibGUgaXQgb24gYW4gaW1wb3J0YW50IGJ1Y2tldCwgd2UgZXNzZW50aWFsbHkganVzdCBicmlja2VkIHRoYXQgYnVja2V0LiBTbyB3ZSBzaG91bGQgbmV2ZXIgd3JpdGUgYW55IGNvZGUgdGhhdCBldmVyIHRyaWVzIHRvIHVzZSBiYWNrYmxhemUgdG8gbWFrZSB0aGluZ3MgaW1tdXRhYmxlLiBcbiAgICBpbW11dGFibGU/OiBib29sZWFuO1xuICAgIC8vIENPUlMgb3JpZ2lucyBhbGxvd2VkIHRvIGNvbnN1bWUgdGhlIGJ1Y2tldCdzIGZpbGVzIGluIGEgYnJvd3Nlci4gTm90IGEgc2VjdXJpdHkgYm91bmRhcnkgKGFjY2VzcyBpcyBnYXRlZCBieSB0aGUgQVBJIGtleSAvIHNpZ25lZCBVUkxzLCBuZWl0aGVyIG9mIHdoaWNoIHJpZGVzIGluIGNvb2tpZXMpIC0gaXQgb25seSBjb250cm9scyB3aGljaCBzaXRlcycgaW4tcGFnZSBKYXZhU2NyaXB0IGNhbiByZWFkIHJlc3BvbnNlcy4gRGVmYXVsdHMgdG8gYW55IEhUVFBTIG9yaWdpbi5cbiAgICBhbGxvd2VkT3JpZ2lucz86IHN0cmluZ1tdO1xuXG4gICAgLy8gTk9URTogV2Ugd2lsbCBhY2Nlc3MgdGhlIGFwaSBrZXkgZnJvbSBnZXRTZWNyZXQsIHNlZSBiYWNrYmxhemUudHMgZm9yIHRoZSBzcGVjaWZpYyBrZXlzLlxufTtcblxuXG5leHBvcnQgY29uc3QgRlVMTF9WQUxJRF9XSU5ET1c6IFtudW1iZXIsIG51bWJlcl0gPSBbMCwgTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVJdO1xuXG5cblxuXG5leHBvcnQgdHlwZSBHZXRDb25maWcgPSB7XG4gICAgcmFuZ2U/OiB7IHN0YXJ0OiBudW1iZXI7IGVuZDogbnVtYmVyIH07XG4gICAgLyoqIFJlYWQgT05MWSBmcm9tIHRoZSBwcmltYXJ5IHNvdXJjZSAtIHRoZSBvbmUgd3JpdGVzIHdvdWxkIHRhcmdldCAtIGluc3RlYWQgb2YgZmFsbGluZyBiYWNrIGFjcm9zcyB0aGUgcmVkdW5kYW50IHNvdXJjZXMuIFVzZSB0aGlzIHdoZW4geW91IHdhbnQgeW91ciByZWFkcyBhbmQgd3JpdGVzIHRvIGJlIHNvbWV3aGF0IGF0b21pYzogdGhlcmUgd2lsbCBzdGlsbCBiZSBpc3N1ZXMgd2l0aCB0aGUgcm91bmQgdHJpcCwgYnV0IHdpdGhvdXQgaXQgeW91IGNvdWxkIHRhbGsgdG8gYSBjb21wbGV0ZWx5IGRpZmZlcmVudCBub2RlIGFuZCBnZXQgYSBtdWNoIG9sZGVyIHZhbHVlLiBNb3N0IHJlYWRzIGFyZW4ndCBmb2xsb3dlZCBieSBhIHdyaXRlIHRob3VnaCwgc28gZm9yIG1vc3QgY2FzZXMgaXQncyBiZXR0ZXIgdG8gZ2V0IGEgdmFsdWUgdGhhbiB0byBoYXZlIHRvIHdhaXQgKG9yIGV2ZW4gdGhyb3cpIHdoZW4gdGhlIHByaW1hcnkgbm9kZSBpcyBub3QgYXZhaWxhYmxlLiAqL1xuICAgIG5vRmFsbGJhY2tzPzogYm9vbGVhbjtcbiAgICAvKiogU3RvcmUtdG8tc3RvcmUgY2FsbDogdGhlIHNlcnZpbmcgbm9kZSBhbnN3ZXJzIHB1cmVseSBmcm9tIGl0cyBvd24gZGlzaywgY29tcGxldGVseSBzaG9ydC1jaXJjdWl0aW5nIGl0cyBpbmRleCBob2xkZXJzIC0gY2hhc2luZyBpdHMgb3duIHJlbW90ZSBob2xkZXJzIHdoaWxlIGFuc3dlcmluZyBhbm90aGVyIHN0b3JlIGlzIGhvdyBpbmZpbml0ZSBnZXQgbG9vcHMgYmV0d2VlbiBzdG9yZXMgZm9ybSAoQSBhc2tzIEIsIEIncyBpbmRleCBwb2ludHMgYmFjayBhdCBBLCAuLi4pLiBObyB3aW5kb3cgb3Igcm91dGUgY2hlY2tzIG9uIHJlYWRzOiBpZiB0aGUgYnl0ZXMgYXJlIG9uIGl0cyBkaXNrLCB0aGUgY2FsbGVyIG1heSBoYXZlIHRoZW0uICovXG4gICAgaW50ZXJuYWw/OiBib29sZWFuO1xuICAgIC8qKiBBbHNvIHJldHVybiBzaXplLTAgcmVzdWx0cyAodG9tYnN0b25lcyAtIGFuIGVtcHR5IGZpbGUgSVMgYSBtaXNzaW5nIGZpbGUpIGluc3RlYWQgb2YgdHJlYXRpbmcgdGhlbSBhcyBhYnNlbnQuIE9mZiBieSBkZWZhdWx0LCBtYXRjaGluZyBnZXRJbmZvJ3MgZmxhZyBvZiB0aGUgc2FtZSBuYW1lLiBTeW5jaHJvbml6YXRpb24gcGFzc2VzIHRoaXMgc28gYSBERUxFVEVEIGZpbGUgKHdpdGggaXRzIHdyaXRlIHRpbWUpIGlzIGRpc3Rpbmd1aXNoYWJsZSBmcm9tIGEgZmlsZSB0aGF0IG5ldmVyIGV4aXN0ZWQuICovXG4gICAgaW5jbHVkZVRvbWJzdG9uZXM/OiBib29sZWFuO1xuICAgIC8qKiBSZWFkcyBmaWxlcyB0aGF0IGFyZSBNQVJLRUQgZm9yIGRlbGV0aW9uIChkZWxldGVkLCBidXQgd2l0aCB0aGVpciBieXRlcyBzdGlsbCBpbiB0aGUgZGVsZXRpb24gaGlzdG9yeSAtIHNlZSBTZXRDb25maWcudW5kZWxldGUgZm9yIHJlc3RvcmluZyB0aGVtKS4gVGhlIGFjdHVhbCBjb250ZW50IGNvbWVzIGJhY2ssIHVubGlrZSBpbmNsdWRlVG9tYnN0b25lcywgd2hpY2ggb25seSByZXBvcnRzIHRoYXQgYSBkZWxldGlvbiBoYXBwZW5lZC4gKi9cbiAgICBpbmNsdWRlTWFya2VkPzogYm9vbGVhbjtcbiAgICAvKiogUmVhZCBmcm9tIEVYQUNUTFkgdGhpcyBzb3VyY2UgLSBpdHMgY29uZmlnIHVybCwgYXMgQXJjaGl2ZXNDaGFpbi5nZXRGaWxlU291cmNlcyBsaXN0cyB0aGVtIC0gd2l0aCBubyBmYWxsYmFjayB0byBhbnkgb3RoZXIuIEZvciBjb21wYXJpbmcgdGhlIGNvcGllcyBkaWZmZXJlbnQgc291cmNlcyBob2xkIChjb21iaW5lIHdpdGggaW50ZXJuYWwgdG8gcmVhZCBvbmx5IHRoYXQgc2VydmVyJ3Mgb3duIGRpc2ssIHNraXBwaW5nIGl0cyBob2xkZXIgcmVzb2x1dGlvbikuIE11bHRpLXNvdXJjZSBhcmNoaXZlcyBvbmx5OyB0aHJvd3Mgd2hlbiBubyBjb25maWd1cmVkIHNvdXJjZSBoYXMgdGhlIHVybC4gKi9cbiAgICBzb3VyY2VVcmw/OiBzdHJpbmc7XG4gICAgLyoqIEhvdyBtYW55IGV4dHJhIHRpbWVzIHRoZSBXSE9MRSBvcGVyYXRpb24gaXMgcmV0cmllZCBhZnRlciBldmVyeSBzb3VyY2UgaW4gYSBwYXNzIGZhaWxlZCAtIGFueSBlcnJvciBjb3VudHMgKHRoZSB3cm9uZy13aW5kb3cvcm91dGUgbWFya2VycyBzdGlsbCBnZXQgdGhlaXIgY29uZmlnIHJlLXJlc29sdmUgZmlyc3QpLiBPbmx5IGFwcGxpZXMgdG8gZmFsbGJhY2sgZGlzcGF0Y2ggKG11bHRpLXNvdXJjZSwgbm90IG5vRmFsbGJhY2tzKSwgd2hlcmUgaXQgZGVmYXVsdHMgdG8gMzsgdGhlIG5vRmFsbGJhY2tzL3dyaXRlLW5vZGUgcGF0aCBhbHJlYWR5IHJldHJpZXMgb24gaXRzIG93biBkZWFkbGluZS4gTXVsdGktcGFydCB1cGxvYWRzIGFkZGl0aW9uYWxseSByZXRyeSBwZXIgcGFydCByZWdhcmRsZXNzIG9mIHRoaXMuICovXG4gICAgcmV0cmllcz86IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIEZpbmRDb25maWcgPSB7XG4gICAgc2hhbGxvdz86IGJvb2xlYW47XG4gICAgdHlwZT86IFwiZmlsZXNcIiB8IFwiZm9sZGVyc1wiO1xuICAgIC8qKiBBbHNvIGxpc3QgZmlsZXMgTUFSS0VEIGZvciBkZWxldGlvbiAoc2VlIEdldENvbmZpZy5pbmNsdWRlTWFya2VkKS4gKi9cbiAgICBpbmNsdWRlTWFya2VkPzogYm9vbGVhbjtcbiAgICAvKiogTGlzdGluZ3Mgbm9ybWFsbHkgY29tZSBPTkxZIGZyb20gdGhlIGF1dGhvcml0YXRpdmUgc291cmNlcyAodGhlIHNhbWUgbm9kZXMgd3JpdGVzIGdvIHRvIC0gcmVhZC15b3VyLXdyaXRlcykuIFdpdGggZmFsbGJhY2tzLCBhIGZhaWxpbmcgc2hhcmQncyByb3V0ZXMgYXJlIGNvdmVyZWQgYnkgdGhlIG5leHQgc291cmNlIGhvbGRpbmcgdGhlbSAoZS5nLiBhIHdpZGUgcmVhZCByZXBsaWNhKSBpbnN0ZWFkIG9mIHRoZSBjYWxsIGZhaWxpbmcgLSBoaWdoIGF2YWlsYWJpbGl0eSBhdCB0aGUgY29zdCBvZiBwb3NzaWJseSBtaXNzaW5nIGp1c3Qtd3JpdHRlbiBkYXRhLiBTaW5nbGUtc291cmNlIGFyY2hpdmVzIGlnbm9yZSB0aGUgZmxhZy4gKi9cbiAgICBmYWxsYmFja3M/OiBib29sZWFuO1xufTtcblxuZXhwb3J0IHR5cGUgRGVsQ29uZmlnID0ge1xuICAgIC8qKiBTdGFtcHMgdGhlIGRlbGV0aW9uIChpdHMgdG9tYnN0b25lKSB3aXRoIHRoaXMgd3JpdGUgdGltZSBpbnN0ZWFkIG9mIG5vdy4gU3luY2hyb25pemF0aW9uIHBhc3NlcyB0aGUgT1JJR0lOQUwgZGVsZXRpb24gdGltZSwgc28gZGVsZXRpb24gb3JkZXJpbmcgc3Vydml2ZXMgcHJvcGFnYXRpb24gZXhhY3RseSBsaWtlIGFueSBvdGhlciB3cml0ZSdzIG9yZGVyaW5nLiAqL1xuICAgIGxhc3RNb2RpZmllZD86IG51bWJlcjtcbiAgICAvKiogU2VlIFNldENvbmZpZy5pbnRlcm5hbC4gKi9cbiAgICBpbnRlcm5hbD86IGJvb2xlYW47XG4gICAgLyoqIFNlZSBTZXRDb25maWcubm9DaGVja3MuICovXG4gICAgbm9DaGVja3M/OiBib29sZWFuO1xuICAgIC8qKiBTZWUgU2V0Q29uZmlnLmZhbGxiYWNrcy4gKi9cbiAgICBmYWxsYmFja3M/OiBib29sZWFuO1xuICAgIC8qKiBTZWUgR2V0Q29uZmlnLnJldHJpZXMuICovXG4gICAgcmV0cmllcz86IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIEdldEluZm9Db25maWcgPSB7XG4gICAgLyoqIEFsc28gcmVwb3J0IHNpemUtMCBlbnRyaWVzICh0b21ic3RvbmVzIC0gYW4gZW1wdHkgZmlsZSBJUyBhIG1pc3NpbmcgZmlsZSkuIE9mZiBieSBkZWZhdWx0LCBzbyBhIGRlbGV0ZWQga2V5IHJlcG9ydHMgdW5kZWZpbmVkLCBtYXRjaGluZyBnZXQuIFN5bmNocm9uaXphdGlvbi1zdHlsZSBjYWxsZXJzIHBhc3MgdGhpcyB3aGVuIHRoZXkgbmVlZCBhIGRlbGV0aW9uJ3Mgd3JpdGUgdGltZSAoZS5nLiB0byBjb21wYXJlIGl0IGFnYWluc3QgYSB3cml0ZSB0aGV5IGFyZSBhYm91dCB0byBtYWtlKS4gKi9cbiAgICBpbmNsdWRlVG9tYnN0b25lcz86IGJvb2xlYW47XG4gICAgLyoqIFNlZSBHZXRDb25maWcubm9GYWxsYmFja3M6IGFuc3dlciBPTkxZIGZyb20gdGhlIHByaW1hcnkgc291cmNlICh0aGUgb25lIHdyaXRlcyB3b3VsZCB0YXJnZXQpIGluc3RlYWQgb2YgZmFsbGluZyBiYWNrIGFjcm9zcyB0aGUgcmVkdW5kYW50IHNvdXJjZXMuICovXG4gICAgbm9GYWxsYmFja3M/OiBib29sZWFuO1xuICAgIC8qKiBTZWUgR2V0Q29uZmlnLnJldHJpZXMuICovXG4gICAgcmV0cmllcz86IG51bWJlcjtcbiAgICAvKiogU2VlIEdldENvbmZpZy5zb3VyY2VVcmw6IGFuc3dlciBmcm9tIEVYQUNUTFkgdGhpcyBzb3VyY2UuICovXG4gICAgc291cmNlVXJsPzogc3RyaW5nO1xufTtcblxuZXhwb3J0IHR5cGUgQ2hhbmdlc0FmdGVyQ29uZmlnID0ge1xuICAgIHRpbWU6IG51bWJlcjtcbiAgICAvKiogT25seSBrZXlzIHJvdXRpbmcgaW50byBvbmUgb2YgdGhlc2UgW3N0YXJ0LCBlbmQpIHJhbmdlcy4gT25seSBzY2FubmluZyBwYXNzZXMgdGhpcyAtIGl0IGxldHMgYSBzdG9yZSBzeW5jaW5nIGEgcGFydGlhbCBzaGFyZCBhc2sgZm9yIGp1c3QgaXRzIHNsaWNlLiAqL1xuICAgIHJvdXRlcz86IFtudW1iZXIsIG51bWJlcl1bXTtcbn07XG5cbmV4cG9ydCB0eXBlIFNldENvbmZpZyA9IHtcbiAgICAvKiogVGhlIHdyaXRlIHRpbWUgdG8gc3RhbXAgKHNlZSBJQXJjaGl2ZXMuc2V0KS4gUk9VTkRFRCB0byB3aG9sZSBtaWxsaXNlY29uZHMgYnkgZXZlcnkgaW1wbGVtZW50YXRpb24gLSB0aGUgZGlzayBjYW4ndCBzdG9yZSBmcmFjdGlvbmFsIG1pbGxpc2Vjb25kcyBhbnl3YXkgKHV0aW1lcyByb3VuZC10cmlwcyB3aG9sZSBtcyksIHNvIGEgZnJhY3Rpb25hbCBzdGFtcCBjb3VsZCBuZXZlciBiZSByZXByb2R1Y2VkIGJ5IHByb3BhZ2F0aW9uIGFuZCB3b3VsZCBjb21wYXJlIFwibmV3ZXJcIiB0aGFuIGl0cyBvd24gY29waWVzIGZvcmV2ZXIuIFJvdW5kZWQgcmF0aGVyIHRoYW4gZmxvb3JlZCBiZWNhdXNlIHV0aW1lcyBnb2VzIHRocm91Z2ggYSBzZWNvbmRzIGRvdWJsZSBhbmQgY2FuIHJlYWQgYmFjayBhIGhhaXIgYmVsb3cgdGhlIHN0YW1wZWQgbWlsbGlzZWNvbmQgKHNlZSBBcmNoaXZlc0Rpc2suZ2V0MikuICovXG4gICAgbGFzdE1vZGlmaWVkPzogbnVtYmVyO1xuICAgIC8qKiBNYWtlcyB0aGUgd3JpdGUgYWNjZXB0YWJsZSBvbiBpbW11dGFibGUgdGFyZ2V0czogYW4gZXhpc3RpbmcgcGF0aCBpcyBzaW1wbHkga2VwdCAoaW1tdXRhYmlsaXR5IHdpbnMgLSBub3RoaW5nIGlzIG92ZXJ3cml0dGVuKSBpbnN0ZWFkIG9mIHRoZSB3cml0ZSB0aHJvd2luZy4gUmVxdWlyZXMgbGFzdE1vZGlmaWVkLiBTeW5jaHJvbml6YXRpb24gTVVTVCBwYXNzIHRoaXMgb24gZXZlcnkgcHVzaCAtIGEgcGxhaW4gc2V0IHRocm93cyBvbiBpbW11dGFibGUgdGFyZ2V0cywgd2hpY2ggd291bGQgYWJvcnQgcmVjb25jaWxpYXRpb24gd2hlbmV2ZXIgb25lIHNvdXJjZSBpbiBhIGNoYWluIGlzIGltbXV0YWJsZS4gKi9cbiAgICBmb3JjZVNldEltbXV0YWJsZT86IGJvb2xlYW47XG4gICAgLyoqIFNraXBzIFJFRFVOREFOVCB0YXJnZXQtc2lkZSBzYWZldHkgcmVhZHMgYXJvdW5kIHRoZSB3cml0ZSAoYmFja2JsYXplOiB0aGUgcG9zdC11cGxvYWQgZXhpc3RlbmNlIHBvbGwpLiBJdCBkb2VzIE5PVCBza2lwIGNoZWNrcyB0aGF0IGFyZSB0aGUgdGFyZ2V0J3Mgb25seSBvcmRlcmluZyBndWFyZDogYmFja2JsYXplJ3MgcHJlLXdyaXRlIGNvbXBhcmlzb24gc3RheXMsIGJlY2F1c2UgYjIgaGFzIG5vIHNlcnZlciBvZiBvdXJzIGVuZm9yY2luZyBvbmx5LXRha2UtdGhlLWxhdGVzdCAtIHdpdGhvdXQgaXQgYSBzdGFsZSBwdXNoIGxhbmRzIG92ZXIgYSBuZXdlciB2YWx1ZSBvciB0b21ic3RvbmUgYW5kIGIyJ3Mgc2VsZi1zdGFtcGVkIHVwbG9hZCB0aW1lIGxhdW5kZXJzIGl0IGludG8gdGhlIG5ld2VzdCBjb3B5IGluIHRoZSBzeXN0ZW0gKGdsb2JhbCByZXN1cnJlY3Rpb24pLiBIb3N0ZWQgdGFyZ2V0cyByZS1jaGVjayBzZXJ2ZXItc2lkZSwgc28gdGhlaXIgY2xpZW50LXNpZGUgc2hvcnRjdXRzIGFyZSBzYWZlLiAqL1xuICAgIG5vQ2hlY2tzPzogYm9vbGVhbjtcbiAgICAvKiogU3RvcmUtdG8tc3RvcmUgcHVzaDogdGhlIHJlY2VpdmluZyBub2RlIHdyaXRlcyBwdXJlbHkgdG8gaXRzIG93biBkaXNrIGFuZCBpbmRleCwgd2l0aCBOTyBkb3duc3RyZWFtIGZhbi1vdXQgKHRoZSBwdXNoaW5nIHN0b3JlIG93bnMgcHJvcGFnYXRpb24gLSBmYW5uaW5nIGl0cyBwdXNoZXMgYmFjayBvdXQgaXMgaG93IHdyaXRlIGxvb3BzIGJldHdlZW4gc3RvcmVzIGZvcm0pLiBXaW5kb3cgYW5kIHJvdXRlIEFSRSBzdGlsbCBjaGVja2VkOiB0aGUgc3RhbXAgbXVzdCBmYWxsIGluc2lkZSBvbmUgb2YgdGhlIHJlY2VpdmVyJ3MgY29uZmlndXJlZCB3aW5kb3dzIGFuZCByb3V0ZXMsIHNvIGEgY29uZnVzZWQgcGVlciBjYW5ub3Qgc3R1ZmYgZGF0YSBvbnRvIGEgbm9kZSB0aGF0IHdhcyBuZXZlciBtZWFudCB0byBob2xkIGl0LiBSZXF1aXJlcyBsYXN0TW9kaWZpZWQuICovXG4gICAgaW50ZXJuYWw/OiBib29sZWFuO1xuICAgIC8qKiBXcml0ZXMgbm9ybWFsbHkgZ28gT05MWSB0byB0aGUgd3JpdGUgbm9kZSAodGhlIGZpcnN0IGN1cnJlbnQtd2luZG93IHNvdXJjZSBjb3ZlcmluZyB0aGUga2V5KSwgcmV0cnlpbmcgaXQgZXZlbiB3aGlsZSBpdCBpcyBkb3duIC0gY29uc2lzdGVudCwgYnV0IHVuYXZhaWxhYmxlIHdoZW4gdGhhdCBub2RlIGlzLiBXaXRoIGZhbGxiYWNrcywgdGhlIHdyaXRlIG5vZGUgaXMgc3RpbGwgdHJpZWQgZmlyc3QsIGJ1dCBvbiBmYWlsdXJlIHRoZSB3cml0ZSBsYW5kcyBvbiB0aGUgbmV4dCBjdXJyZW50LXdpbmRvdyBzb3VyY2UgY292ZXJpbmcgdGhlIGtleSAoc3luY2hyb25pemF0aW9uIG1vdmVzIGl0IHRvIHRoZSB3cml0ZSBub2RlIGxhdGVyKSAtIGF2YWlsYWJpbGl0eSBhdCB0aGUgY29zdCBvZiByZWFkcyBwb3NzaWJseSBtaXNzaW5nIHRoZSB3cml0ZSB1bnRpbCBpdCBwcm9wYWdhdGVzLiBTaW5nbGUtc291cmNlIGFyY2hpdmVzIGlnbm9yZSB0aGUgZmxhZy4gKi9cbiAgICBmYWxsYmFja3M/OiBib29sZWFuO1xuICAgIC8qKiBTZWUgR2V0Q29uZmlnLnJldHJpZXMuICovXG4gICAgcmV0cmllcz86IG51bWJlcjtcbiAgICAvKiogVGhlIHNldCBpcyBub3QgYSB3cml0ZSBhdCBhbGw6IGl0IFJFU1RPUkVTIGEgZmlsZSBtYXJrZWQgZm9yIGRlbGV0aW9uLCBmbGlwcGluZyBpdHMgaW5kZXggZW50cnkgYmFjayB0byBsaXZlICh3aXRoIGEgZnJlc2ggd3JpdGUgdGltZSwgc28gdGhlIHJlc3RvcmUgb3V0cmFua3MgdGhlIGRlbGV0aW9uIGV2ZXJ5d2hlcmUgaXQgcHJvcGFnYXRlZCkgLSB0aGUgYnl0ZXMgbmV2ZXIgbGVmdCB0aGUgZGlzaywgc28gcmVhZHMganVzdCB3b3JrIGFnYWluLiBUaGUgZGF0YSBidWZmZXIgaXMgaWdub3JlZCAoYSAxLWJ5dGUgcGxhY2Vob2xkZXIgc2F0aXNmaWVzIHRoZSBlbXB0eS1idWZmZXIgcnVsZSk7IHVzZSBJQXJjaGl2ZXMudW5kZWxldGUgcmF0aGVyIHRoYW4gcGFzc2luZyB0aGlzIHlvdXJzZWxmLiBUaHJvd3Mgd2hlbiB0aGUga2V5IGhhcyBubyBtYXJrZWQgZGVsZXRpb24gdG8gcmVzdG9yZSAoaXRzIGhpc3Rvcnkgd2FzIGRyb3BwZWQsIG9yIGl0IHdhcyBuZXZlciBkZWxldGVkKS4gKi9cbiAgICB1bmRlbGV0ZT86IGJvb2xlYW47XG59O1xuXG4vKiogc2V0TGFyZ2VGaWxlJ3MgY29uZmlnOiBhIFNldENvbmZpZyAoaXQgSVMgYSBzZXQgLSB0aGUgc2FtZSBpbW11dGFiaWxpdHksIG9yZGVyaW5nLCBpbnRlcm5hbCwgYW5kIGZhbGxiYWNrcyBydWxlcyBhcHBseSkgcGx1cyB0aGUgc3RyZWFtIGNhcnJ5aW5nIHRoZSBieXRlcy4gKi9cbmV4cG9ydCB0eXBlIFNldExhcmdlRmlsZUNvbmZpZyA9IFNldENvbmZpZyAmIHtcbiAgICBwYXRoOiBzdHJpbmc7XG4gICAgZ2V0TmV4dERhdGEoKTogUHJvbWlzZTxCdWZmZXIgfCB1bmRlZmluZWQ+O1xuICAgIC8qKiBSZXdpbmRzIHRoZSBzdHJlYW0gdG8gaXRzIGZpcnN0IGJ5dGUuIFdpdGhvdXQgaXQgdGhlIHdyaXRlIGdldHMgZXhhY3RseSBPTkUgYXR0ZW1wdDogYSByZXRyeSAoYSBmYWxsYmFjayBzb3VyY2UsIG9yIHRoZSB3cml0ZSBub2RlIGNvbWluZyBiYWNrKSB3b3VsZCB1cGxvYWQgd2hhdGV2ZXIgaXMgbGVmdCBvZiBhbiBhbHJlYWR5LWNvbnN1bWVkIHN0cmVhbSBhcyBpZiBpdCB3ZXJlIHRoZSB3aG9sZSBmaWxlLiBDYWxsZXJzIGhvbGRpbmcgdGhlIGRhdGEgKGEgYnVmZmVyLCBvciBhIHNvdXJjZSB0aGV5IGNhbiByZS1yZWFkKSBhbHdheXMgcGFzcyBpdCAtIGEgbGFyZ2Ugc2V0IHdpdGggZmFsbGJhY2tzIGlzIG9ubHkgYXMgYXZhaWxhYmxlIGFzIHRoaXMuICovXG4gICAgcmVzdGFydFN0cmVhbT8oKTogUHJvbWlzZTx2b2lkPiB8IHZvaWQ7XG59O1xuXG4vLyBjcmVhdGVUaW1lIGlzIGEgbWlzbm9tZXIga2VwdCBmb3IgY29tcGF0aWJpbGl0eSDigJQgaXQgaXMgcmVhbGx5IHRoZSBMQVNULVdSSVRFIHRpbWUsIHNhbWUgYXMgZ2V0SW5mbydzIHdyaXRlVGltZS4gTmVpdGhlciBCYWNrYmxhemUgbm9yIG91ciByZW1vdGUgc3RvcmFnZSB0cmFja3MgYSBkaXN0aW5jdCBjcmVhdGlvbiBkYXRlOiBlYWNoIHdyaXRlIHN0YW1wcyBhIGZyZXNoIHRpbWVzdGFtcCBvbiB0aGUgY3VycmVudCB2ZXJzaW9uLCBzbyBib3RoIGZpZWxkcyBhcmUganVzdCBcIndoZW4gdGhlIGJ5dGVzIHNlcnZlZCBieSBnZXQoKSB3ZXJlIG1vc3QgcmVjZW50bHkgd3JpdHRlblwiLiBBbHdheXMgV0hPTEUgbWlsbGlzZWNvbmRzOiB3cml0ZSB0aW1lcyBhcmUgcm91bmRlZCBhdCBldmVyeSBwcm9kdWNlciAoc2VlIFNldENvbmZpZy5sYXN0TW9kaWZpZWQpLlxuZXhwb3J0IHR5cGUgQXJjaGl2ZUZpbGVJbmZvID0geyBwYXRoOiBzdHJpbmc7IGNyZWF0ZVRpbWU6IG51bWJlcjsgc2l6ZTogbnVtYmVyIH07XG5cbi8vIEFuIGluLXByb2dyZXNzIGJhY2tncm91bmQgc3luY2hyb25pemF0aW9uIHRhc2sgKHNlZSBBcmNoaXZlc0NvbmZpZy5zeW5jaW5nKVxuZXhwb3J0IHR5cGUgU3luY0FjdGl2aXR5ID0ge1xuICAgIC8vIEEgbWV0YWRhdGEgc2NhbiBpcyBhIHNpbmdsZSBsaXN0aW5nIGNhbGwsIHNvIGl0IGhhcyBubyBpbmNyZW1lbnRhbCBwcm9ncmVzcyAtIGp1c3QgdGhhdCBpdCdzIHJ1bm5pbmcgYW5kIHNpbmNlIHdoZW4uIEEgZnVsbCBzeW5jIGtub3dzIGl0cyBleGFjdCBmaWxlL2J5dGUgcHJvZ3Jlc3MuXG4gICAgdHlwZTogXCJtZXRhZGF0YVNjYW5cIiB8IFwiZnVsbFN5bmNcIjtcbiAgICBzb3VyY2VEZWJ1Z05hbWU6IHN0cmluZztcbiAgICBzdGFydFRpbWU6IG51bWJlcjtcbiAgICBkb25lRmlsZXM/OiBudW1iZXI7XG4gICAgdG90YWxGaWxlcz86IG51bWJlcjtcbiAgICBkb25lQnl0ZXM/OiBudW1iZXI7XG4gICAgdG90YWxCeXRlcz86IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIEFyY2hpdmVzQ29uZmlnID0ge1xuICAgIC8vIFdoZXRoZXIgZ2V0Q2hhbmdlc0FmdGVyMiBpcyBuYXRpdmVseSBpbmRleC1iYWNrZWQgKGZhc3QgY2hhbmdlIHBvbGxpbmc7IGV2ZXJ5IGJhY2tlbmQgc3RpbGwgc2VydmVzIGl0LCBidXQgdGhlIG90aGVycyBlbXVsYXRlIGl0IHdpdGggYSBmdWxsIGxpc3RpbmcpXG4gICAgc3VwcG9ydHNDaGFuZ2VzQWZ0ZXI/OiBib29sZWFuO1xuICAgIC8vIFRoZSBidWNrZXQncyBmdWxsIHJvdXRpbmcgY29uZmlnIChST1VUSU5HX0ZJTEUpLiBBYnNlbnQgZm9yIHNvdXJjZXMgdGhhdCBkb24ndCBoYXZlIG9uZSAoYSBiYXJlIGRpc2sgc291cmNlLCBvciBhIGJ1Y2tldCB0aGF0IGRvZXNuJ3QgZXhpc3QgeWV0KS5cbiAgICByZW1vdGVDb25maWc/OiBSZW1vdGVDb25maWc7XG4gICAgLy8gTGl2ZSBpbmRleCB0b3RhbHMgKHRvbWJzdG9uZXMgZXhjbHVkZWQpLCBrZXB0IHVwIHRvIGRhdGUgaW4gbWVtb3J5IG9uIGV2ZXJ5IG11dGF0aW9uIGFuZCByZWNvbXB1dGVkIG9uIGxvYWQgLSBzbyBhbnkgZHJpZnQgaGVhbHMgb24gcmVzdGFydFxuICAgIGluZGV4PzogeyBmaWxlQ291bnQ6IG51bWJlcjsgYnl0ZUNvdW50OiBudW1iZXIgfTtcbiAgICAvKiogRmlsZXMgTUFSS0VEIGZvciBkZWxldGlvbiAoZGVsZXRlZCwgYnl0ZXMgc3RpbGwga2VwdCBhcyBoaXN0b3J5IC0gc2VlIFNldENvbmZpZy51bmRlbGV0ZSk6IGhvdyBtYW55LCBob3cgYmlnLCBhbmQgdGhlIGRlbGV0ZSB0aW1lIG9mIHRoZSBvbGRlc3Qgb25lIC0gd2hpY2ggaXMgaG93IGZhciBiYWNrIHRoZSBkZWxldGlvbiBoaXN0b3J5IHJlYWNoZXMuICovXG4gICAgbWFya2VkSW5kZXg/OiB7IGZpbGVDb3VudDogbnVtYmVyOyBieXRlQ291bnQ6IG51bWJlcjsgb2xkZXN0RGVsZXRlVGltZT86IG51bWJlciB9O1xuICAgIC8vIFRoZSBzYW1lIHRvdGFscyBicm9rZW4gZG93biBieSB3aGljaCBzb3VyY2UgY3VycmVudGx5IGhvbGRzIGVhY2ggZmlsZSdzIGJ5dGVzICh0aGUgZmlyc3QgZW50cnkgaXMgdGhlIHNlcnZlcidzIG93biBkaXNrKVxuICAgIGluZGV4U291cmNlcz86IHsgZGVidWdOYW1lOiBzdHJpbmc7IGZpbGVDb3VudDogbnVtYmVyOyBieXRlQ291bnQ6IG51bWJlciB9W107XG4gICAgLy8gVGhlIHNlcnZlcidzIGNvbmZpZ3VyZWQgcmVhZGVyRGlza0xpbWl0LCB3aGVuIGl0IHJ1bnMgYXMgYSBib3VuZGVkIHJlYWQgY2FjaGVcbiAgICByZWFkZXJEaXNrTGltaXQ/OiBudW1iZXI7XG4gICAgLy8gQmFja2dyb3VuZCBzeW5jaHJvbml6YXRpb24gY3VycmVudGx5IGluIHByb2dyZXNzIChlbXB0eSB3aGVuIGlkbGUpXG4gICAgc3luY2luZz86IFN5bmNBY3Rpdml0eVtdO1xufTtcblxuLy8gQSBzeW5jaHJvbml6YXRpb24gc291cmNlIG9mIGEgQmxvYlN0b3JlICh3aGljaCBzeW5jaHJvbml6ZXMgYW4gaW5kZXggKyBsb2NhbCBjYWNoZSBmcm9tIHRoZW0pXG5leHBvcnQgdHlwZSBBcmNoaXZlc1NvdXJjZSA9IHtcbiAgICBzb3VyY2U6IElBcmNoaXZlcztcbiAgICAvKiogVGhlIHBlcnNpc3RlbnQgaWRlbnRpdHkgb2YgdGhlIGVuZHBvaW50OiBpdHMgcm91dGluZyBVUkwgKGhvc3RlZC9iYWNrYmxhemUpLCBvciB0aGUgZGlzayBmb2xkZXIgcGF0aCBmb3IgdGhlIGJhc2UgZGlzayBzb3VyY2UuIFRoZSBzdG9yZSBwZXJzaXN0cyB0aGlzICh2aWEgaXRzIGFwcGVuZC1vbmx5IHNvdXJjZXMgbGlzdCkgYXMgSW5kZXhFbnRyeS5zb3VyY2VzTGlzdEluZGV4LCBzbyBpdCBtdXN0IG1lYW4gdGhlIHNhbWUgZW5kcG9pbnQgZm9yZXZlci4gKi9cbiAgICB1cmw6IHN0cmluZztcbiAgICAvLyBGcm9tIHRoZSBzb3VyY2UncyBDb21tb25Db25maWcsIGJ1dCBBTEwgb2YgdGhlbTogdGhlIHNhbWUgZW5kcG9pbnQgKHNhbWUgdXJsK3JvdXRlLCBpZ25vcmluZyB0aGUgd2luZG93KSBjYW4gYXBwZWFyIGluIHRoZSByb3V0aW5nIGNvbmZpZyB1bmRlciBzZXZlcmFsIHdpbmRvd3MgYXQgb25jZSAtIG1vc3QgY29tbW9ubHkgd2hlbiBhIGRlcGxveSBzd2l0Y2hvdmVyIGhhcyBzcGxpdCBvbmUgd2luZG93IGluIHR3byBhcm91bmQgYW4gaW50ZXJtZWRpYXRlLiBJdCBpcyBPTkUgc291cmNlIHRoYXQga25vd3MgYWxsIGl0cyB3aW5kb3dzLCBuZXZlciBzZXZlcmFsIHNvdXJjZXMuIFRoZSB3aW5kb3cgcm91dGVzIFdSSVRFUzogdGhlIHNvdXJjZSByZWNlaXZlcyB3cml0ZXMgd2hpbGUgQU5ZIG9mIGl0cyB3aW5kb3dzIGlzIHN0aWxsIG9wZW4gKHNlZSB3aW5kb3dzQWNjZXB0V3JpdGVzKS4gV2luZG93cyBkbyBOT1QgZmlsdGVyIHNjYW5uaW5nOiBhIHNjYW4gaXMgdXMgYXNraW5nIHRoZSBzb3VyY2Ugd2hhdCBpdCBhbHJlYWR5IGhvbGRzLCBhbmQgZXhpc3RpbmcgdmFsdWVzIHN5bmNocm9uaXplIHJlZ2FyZGxlc3Mgb2YgdGhlaXIgd3JpdGUgdGltZXMgKHRoZSBzYW1lIHJlYXNvbmluZyB0aGF0IGxldHMgc3luY2hyb25pemF0aW9uIGlnbm9yZSB0aGUgaW1tdXRhYmxlIGZsYWcpLlxuICAgIHZhbGlkV2luZG93czogW251bWJlciwgbnVtYmVyXVtdO1xuICAgIC8vIEZyb20gdGhlIHNvdXJjZSdzIENvbW1vbkNvbmZpZyAoaW50ZXJzZWN0ZWQgd2l0aCB0aGUgb3duaW5nIHN0b3JlJ3Mgb3duIHJvdXRlKTogb25seSBrZXlzIHJvdXRpbmcgaW50byBbc3RhcnQsIGVuZCkgYXJlIGFjY2VwdGVkIGZyb20gdGhpcyBzb3VyY2UncyBzY2FucyBhbmQgc2VudCB0byBpdCBpbiB3cml0ZXMvcmVjb25jaWxpYXRpb24uIFRoZSByb3V0aW5nIGZpbGUgaXMgZXhlbXB0IC0gY29uZmlnIGZsb3dzIGV2ZXJ5d2hlcmUuIEFic2VudCA9IGFsbCBrZXlzLlxuICAgIHJvdXRlPzogW251bWJlciwgbnVtYmVyXTtcbiAgICAvLyBGcm9tIHRoZSBzb3VyY2UncyBDb21tb25Db25maWc7IHNlZSB0aGVyZS5cbiAgICBub0Z1bGxTeW5jPzogYm9vbGVhbjtcbiAgICAvLyBGcm9tIHRoZSBzb3VyY2UncyBDb21tb25Db25maWc6IGEgZGVwbG95IHN3aXRjaG92ZXIncyB0ZW1wb3JhcnkgYWx0ZXJuYXRlLXBvcnQgZW50cnkgKHRoZSB2YWx1ZSBpcyB0aGUgdXJsIG9mIHRoZSBzb3VyY2UgaXQgd2FzIHNwbGl0IG91dCBvZikuIE9uY2UgaXRzIHdpbmRvdyBpcyBwYXN0LCB0aGUgcG9ydCBpdCBwb2ludHMgYXQgaXMgZ29uZSBmb3IgZ29vZCAtIHNvIGl0IGlzIG5ldmVyIHNjYW5uZWQgdGhlbiwgYW5kIHNjYW4gZmFpbHVyZXMgYXJlIG5ldmVyIHJldHJpZWQuXG4gICAgaW50ZXJtZWRpYXRlPzogc3RyaW5nO1xuICAgIC8vIFRoZSByb3V0aW5nLWNvbmZpZyBlbnRyeSB0aGlzIHNvdXJjZSB3YXMgYnVpbHQgZnJvbSAoYWJzZW50IGZvciB0aGUgYmFzZSBkaXNrIHNvdXJjZSkuIEl0cyBgdHlwZWAgZGVjaWRlcyBmYXN0LXdyaXRlIGZsdXNoIHRpbWluZzogdHlwZS1cInJlbW90ZVwiIGRvd25zdHJlYW0gc291cmNlcyAob3VyIG93biBzdG9yYWdlIHNlcnZlcnMpIGZsdXNoIHF1aWNrbHkgKGNoZWFwLCBhbmQgd2Ugd2FudCBjcm9zcy1ub2RlIHJlZHVuZGFuY3kgZmFzdCksIHdoaWxlIG90aGVycyAoZS5nLiBiYWNrYmxhemUpIGtlZXAgdGhlIGZ1bGwgd3JpdGVEZWxheSBzbyBleHBlbnNpdmUgZXh0ZXJuYWwgd3JpdGVzIHN0YXkgY29hbGVzY2VkLiBUaGUgd2luZG93L3JvdXRlIE9OIHRoaXMgY29uZmlnIGFyZSB0aGUgU09VUkNFJ3Mgb3duOyBBcmNoaXZlc1NvdXJjZS52YWxpZFdpbmRvdy9yb3V0ZSBhcmUgd2hhdCB0aGUgb3duaW5nIHN0b3JlIGFjdHVhbGx5IHVzZXMgKHJvdXRlIGlzIGludGVyc2VjdGVkIHdpdGggdGhlIHN0b3JlJ3Mgcm91dGUpLlxuICAgIHNvdXJjZUNvbmZpZz86IFNvdXJjZUNvbmZpZztcbiAgICAvLyBTdGFibGUgaWRlbnRpdHkgb2YgdGhlIHVuZGVybHlpbmcgZW5kcG9pbnQgKGl0cyBjb25maWcgd2l0aCB3aW5kb3dzL3JvdXRlcyBzdHJpcHBlZCkgLSBob3cgQmxvYlN0b3JlLnVwZGF0ZVNvdXJjZXMgcmVjb2duaXplcyBhIHNvdXJjZSBhY3Jvc3MgY29uZmlnIGNoYW5nZXMgc28gaXQgY2FuIHVwZGF0ZSBpdCBpbiBwbGFjZSBpbnN0ZWFkIG9mIHJlbW92aW5nIGFuZCByZS1hZGRpbmcgaXRcbiAgICBpZGVudGl0eT86IHN0cmluZztcbn07XG5cbi8vIEVycm9yIG1hcmtlciBhIHNlcnZlciBpbmNsdWRlcyB3aGVuIGEgZnJlc2hseS1zdGFtcGVkIHdyaXRlIHJlYWNoZXMgaXQgb3V0c2lkZSBpdHMgdmFsaWQgd2luZG93cyAodGhlIGNsaWVudCByZXNvbHZlZCBpdHMgdGFyZ2V0LCB0aGVuIHRpbWUgY3Jvc3NlZCBhIHdpbmRvdyBib3VuZGFyeSBiZWZvcmUgdGhlIHdyaXRlIGxhbmRlZCkuIENsaWVudHMgZGV0ZWN0IHRoaXMgbWFya2VyIGFuZCByZS1yZXNvbHZlIHRoZSBjdXJyZW50bHktdmFsaWQgc291cmNlLCByZXRyeWluZyBPTkNFIC0gYm91bmRhcmllcyBhcmUgZmFyIGFwYXJ0LCBzbyBoaXR0aW5nIGl0IHR3aWNlIGluIG9uZSBhdHRlbXB0IG1lYW5zIHNvbWV0aGluZyBpcyBhY3R1YWxseSB3cm9uZy5cbmV4cG9ydCBjb25zdCBTVE9SQUdFX1dST05HX1ZBTElEX1dJTkRPVyA9IFwiUkVNT1RFX1NUT1JBR0VfV1JPTkdfVkFMSURfV0lORE9XX2E3YzFmMDRlXCI7XG5cbi8vIEVycm9yIG1hcmtlciBhIHNlcnZlciBpbmNsdWRlcyB3aGVuIGEgZnJlc2hseS1zdGFtcGVkIHdyaXRlJ3Mga2V5IHJvdXRlcyBvdXRzaWRlIHRoZSBzaGFyZHMgdGhpcyBzZXJ2ZXIgaGFuZGxlcyAodGhlIGNsaWVudCdzIGNvbmZpZyBkaXNhZ3JlZXMgd2l0aCB0aGUgc2VydmVyJ3MgLSBjbGllbnRzIHJlLXJlc29sdmUgb25jZSlcbmV4cG9ydCBjb25zdCBTVE9SQUdFX1dST05HX1JPVVRFID0gXCJSRU1PVEVfU1RPUkFHRV9XUk9OR19ST1VURV9jOTRkMmUxN1wiO1xuXG4vLyBFcnJvciBtYXJrZXIgYSBzZXJ2ZXIgaW5jbHVkZXMgd2hlbiBhIHdyaXRlIHJlYWNoZXMgYSBzdG9yZSB3aG9zZSBvd24gcm91dGluZyBjb25maWcgaGFzIE5PIGVudHJ5IGZvciBpdCBvbiB0aGF0IHNlcnZlciAob3IgdGhhdCBoYXMgbm8gcm91dGluZyBjb25maWcgYXQgYWxsKSAtIGFjY2VwdGluZyB0aGUgd3JpdGUgd291bGQgc3RvcmUgZGF0YSBub3RoaW5nIHNjYW5zIG9yIHJlY29uY2lsZXMuIENsaWVudHMgcmUtcmVzb2x2ZSBvbmNlLCBleGFjdGx5IGxpa2UgdGhlIG1hcmtlcnMgYWJvdmU6IHRoZSB1c3VhbCBjYXVzZSBpcyB0aGUgY2xpZW50IHJ1bm5pbmcgYSBkaWZmZXJlbnQgY29uZmlnIHRoYW4gdGhlIHN0b3JlLlxuZXhwb3J0IGNvbnN0IFNUT1JBR0VfTk9UX0NPTkZJR1VSRUQgPSBcIlJFTU9URV9TVE9SQUdFX05PVF9DT05GSUdVUkVEX2U1MWI3ZDkyXCI7XG5cbmV4cG9ydCBjb25zdCBGVUxMX1JPVVRFOiBbbnVtYmVyLCBudW1iZXJdID0gWzAsIDFdO1xuXG4vLyBBIGtleSBjb250YWluaW5nIHRoaXMgc2VudGluZWwgZG9lc24ndCBoYXZlIGEgZml4ZWQgc2hhcmQ6IHNldFZhcmlhYmxlU2hhcmQgcGlja3MgdGhlIChsb3dlc3QgbGF0ZW5jeSwgdXApIHdyaXRlIHNoYXJkLCBhcHBlbmRzIFwiXzx2YWx1ZSBpbiB0aGUgc2hhcmQncyByb3V0ZT5cIiBkaXJlY3RseSBhZnRlciB0aGUgc2VudGluZWwsIGFuZCByZXR1cm5zIHRoZSBtYXRlcmlhbGl6ZWQga2V5LiBnZXRSb3V0ZSB0cmVhdHMgdGhhdCBzdWZmaXggYXMgYSBjb21wbGV0ZSByb3V0ZSBvdmVycmlkZS5cbmV4cG9ydCBjb25zdCBWQVJJQUJMRV9TSEFSRCA9IFwiVkFSSUFCTEVfU0hBUkRfZjAyMzRqZmFoMDhmZ3loZmd5c3NkZHM4M25tcFwiO1xuLy8gTm8gZ3JhY2UgcGFzdCB0aGUgZW5kOiBhIHdpbmRvdyBib3VuZGFyeSBpcyBhIGhhcmQgaGFuZG9mZiAoY2xpZW50cyByZXRyeSBhIHJlamVjdGVkIHdyaXRlIGFnYWluc3QgdGhlIG5ld2x5LXZhbGlkIHNvdXJjZSwgc28gbGVuaWVuY3kgaGVyZSB3b3VsZCBvbmx5IGRlc3luY2hyb25pemUgdGhlIGhhbmRvZmYpXG4vLyAgLSBXcml0aW5nIHRvIG9sZGVyIHZhbGlkIHN0YXRlIHdpbmRvd3MgaXMgZmluZSwgdGhvdWdoLiBXZSBuZWVkIHRoaXMgdG8gaW5nZXN0IHRoZSBvbGQgZGF0YSB3aGVuIHdlJ3JlIHN5bmNocm9uaXppbmcgbm9kZXMgdG8gZ2V0IHRoZW0gdXAgdG8gZGF0ZSBhbnl3YXkuIFxuZXhwb3J0IGZ1bmN0aW9uIHdpbmRvd0FjY2VwdHNXcml0ZXModmFsaWRXaW5kb3c6IFtudW1iZXIsIG51bWJlcl0gfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgICBpZiAoIXZhbGlkV2luZG93KSByZXR1cm4gdHJ1ZTtcbiAgICByZXR1cm4gdmFsaWRXaW5kb3dbMV0gPiBEYXRlLm5vdygpO1xufVxuLy8gQSBzb3VyY2UgKHdoaWNoIGNhbiBob2xkIHNldmVyYWwgd2luZG93cykgYWNjZXB0cyB3cml0ZXMgd2hpbGUgQU5ZIG9mIGl0cyB3aW5kb3dzIGlzIHN0aWxsIG9wZW4uIE5vIHdpbmRvd3MgPSB0aGUgYmFzZSBkaXNrIG9mIGFuIGluZXJ0IHN0b3JlIChub3QgaW4gdGhlIGNvbmZpZyksIHdoaWNoIG5ldmVyIHJlY2VpdmVzIGZhbi1vdXQgd3JpdGVzIGFueXdheS5cbmV4cG9ydCBmdW5jdGlvbiB3aW5kb3dzQWNjZXB0V3JpdGVzKHZhbGlkV2luZG93czogW251bWJlciwgbnVtYmVyXVtdKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHZhbGlkV2luZG93cy5zb21lKHdpbmRvd0FjY2VwdHNXcml0ZXMpO1xufVxuXG4vLyBBYm92ZSB0aGlzLCBzZXQgdHJhbnNwYXJlbnRseSBzdHJlYW1zIHRocm91Z2ggc2V0TGFyZ2VGaWxlOiBvbmUgZ2lhbnQgd2lyZSBtZXNzYWdlIHdvdWxkIGV4Y2VlZCB0aGUgdHJhbnNwb3J0IGxpbWl0IGFuZCBsYWcgZXZlcnkgb3RoZXIgY2xpZW50IHNoYXJpbmcgdGhlIGNvbm5lY3Rpb25cbmV4cG9ydCBjb25zdCBMQVJHRV9TRVRfVEhSRVNIT0xEID0gOCAqIDEwMjQgKiAxMDI0O1xuXG4vKiogVGhlIHNldExhcmdlRmlsZSBzdHJlYW0gb3ZlciBhbiBpbi1tZW1vcnkgYnVmZmVyLCBpbiBMQVJHRV9TRVRfVEhSRVNIT0xEIHNsaWNlcyAtIGhvdyBzZXQgdHJhbnNwYXJlbnRseSBiZWNvbWVzIHNldExhcmdlRmlsZSBmb3IgbGFyZ2UgYnVmZmVycy4gU3ByZWFkIGludG8gdGhlIGNvbmZpZzogaXQgcHJvdmlkZXMgYm90aCBnZXROZXh0RGF0YSBhbmQgcmVzdGFydFN0cmVhbSAodGhlIGJ1ZmZlciBpcyBzdGlsbCBoZWxkLCBzbyBhIHJldHJ5IGNvc3RzIG5vdGhpbmcpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJ1ZmZlckNodW5rU3RyZWFtKGRhdGE6IEJ1ZmZlcik6IHsgZ2V0TmV4dERhdGEoKTogUHJvbWlzZTxCdWZmZXIgfCB1bmRlZmluZWQ+OyByZXN0YXJ0U3RyZWFtKCk6IHZvaWQgfSB7XG4gICAgbGV0IG9mZnNldCA9IDA7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZ2V0TmV4dERhdGE6IGFzeW5jICgpID0+IHtcbiAgICAgICAgICAgIGlmIChvZmZzZXQgPj0gZGF0YS5sZW5ndGgpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgICAgICBsZXQgY2h1bmsgPSBkYXRhLnN1YmFycmF5KG9mZnNldCwgb2Zmc2V0ICsgTEFSR0VfU0VUX1RIUkVTSE9MRCk7XG4gICAgICAgICAgICBvZmZzZXQgKz0gY2h1bmsubGVuZ3RoO1xuICAgICAgICAgICAgcmV0dXJuIGNodW5rO1xuICAgICAgICB9LFxuICAgICAgICByZXN0YXJ0U3RyZWFtOiAoKSA9PiB7XG4gICAgICAgICAgICBvZmZzZXQgPSAwO1xuICAgICAgICB9LFxuICAgIH07XG59XG5cbi8vIFJlLWV4cG9ydGVkIGZvciB0aGUgZXhpc3RpbmcgaW1wb3J0ZXJzIC0gdGhlIGltcGxlbWVudGF0aW9ucyAoYW5kIG1vdmVBcmNoaXZlRmlsZSkgbGl2ZSBpbiBhcmNoaXZlSGVscGVycy50cywgYmVzaWRlIHRoaXMgaW50ZXJmYWNlIHJhdGhlciB0aGFuIGluIGl0XG5leHBvcnQgeyBjb3B5QXJjaGl2ZUZpbGUgfSBmcm9tIFwiLi9hcmNoaXZlSGVscGVyc1wiO1xuXG4vKiogbW92ZSdzIGNvbmZpZy4gVGhlcmUgaXMgZGVsaWJlcmF0ZWx5IG5vIGxhc3RNb2RpZmllZDogdGhlIGRlc3RpbmF0aW9uIGlzIEFMV0FZUyBzdGFtcGVkIGZyZXNoIChzZWUgSUFyY2hpdmVzLm1vdmUpIC0gYSBtb3ZlIGlzIGEgbmV3IHdyaXRlIGF0IHRoZSBuZXcgcGF0aCwgYW5kIGEgcHJlc2VydmVkIG9sZCBzdGFtcCBpcyBob3cgYSBtb3ZlZCBmaWxlIGxvc2VzIHRvIGEgc3RhbGUgdG9tYnN0b25lIHRoZXJlIGFuZCB2YW5pc2hlcy4gKi9cbmV4cG9ydCB0eXBlIE1vdmVGaWxlQ29uZmlnID0ge1xuICAgIGZyb21QYXRoOiBzdHJpbmc7XG4gICAgdG9QYXRoOiBzdHJpbmc7XG59O1xuXG5leHBvcnQgdHlwZSBBcmNoaXZlc1N5bmNTb3VyY2VTdGF0dXMgPSB7XG4gICAgZGVidWdOYW1lOiBzdHJpbmc7XG4gICAgdmFsaWRXaW5kb3dzOiBbbnVtYmVyLCBudW1iZXJdW107XG4gICAgcm91dGU/OiBbbnVtYmVyLCBudW1iZXJdO1xuICAgIG5vRnVsbFN5bmM/OiBib29sZWFuO1xuICAgIHN1cHBvcnRzQ2hhbmdlc0FmdGVyOiBib29sZWFuO1xuICAgIGluaXRpYWxTY2FuQ29tcGxldGU6IGJvb2xlYW47XG4gICAgLy8gRmlsZXMgc2VlbiBpbiB0aGlzIHNvdXJjZSdzIHNjYW5zIC8gY2hhbmdlIHBvbGxzIHNvIGZhclxuICAgIHNjYW5uZWRDb3VudDogbnVtYmVyO1xufTtcbmV4cG9ydCB0eXBlIEFyY2hpdmVzU3luY1N0YXR1cyA9IHtcbiAgICBhbGxTY2Fuc0NvbXBsZXRlOiBib29sZWFuO1xuICAgIC8vIE51bWJlciBvZiBmaWxlcyBpbiB0aGUgaW5kZXhcbiAgICBpbmRleFNpemU6IG51bWJlcjtcbiAgICBzb3VyY2VzOiBBcmNoaXZlc1N5bmNTb3VyY2VTdGF0dXNbXTtcbn07XG5cbi8vIE5PVEU6IFdlIGRvbid0IHByZXNlbnRseSBoYXZlIGFuIGFwcGVuZCBmdW5jdGlvbiBoZXJlIGJlY2F1c2UgYSBzdXJwcmlzaW5nIG51bWJlciBvZiBzdG9yYWdlIHN5c3RlbXMgZG9uJ3Qgc3VwcG9ydCBpdCAoYmFja2JsYXplLCBmaWxlIHN5c3RlbSBhcGkpLiBJdCB3b3VsZCBhbHNvIGNvbXBsaWNhdGUgdGhpbmdzIGFzIG5vdyB0aGVyZSBuZWVkcyB0byBiZSByZWFsbHkgYSBzaW5nbGUgc291cmNlIG9mIHRydXRoIG9mIGEgZmlsZSwgYW5kIGlmIHlvdSBhcHBlbmQgdG8gdGhlIHdyb25nIHNpbmdsZSBzb3VyY2Ugb2YgdHJ1dGgsIHRoaW5ncyBqdXN0IGJlY29tZSB2ZXJ5IGNvbXBsaWNhdGVkLiBcbmV4cG9ydCBpbnRlcmZhY2UgSUFyY2hpdmVzIHtcbiAgICBnZXREZWJ1Z05hbWUoKTogc3RyaW5nO1xuICAgIC8qKiBXaGV0aGVyIHdyaXRlcyB3b3VsZCBiZSBhY2NlcHRlZCAoY3JlZGVudGlhbHMgZXhpc3QsIHRoZSBhY2NvdW50IHRydXN0cyB0aGlzIG1hY2hpbmUsIGV0YykuIENoZWNrZWQgd2l0aG91dCB3cml0aW5nIGFueXRoaW5nLiAqL1xuICAgIGhhc1dyaXRlQWNjZXNzKCk6IFByb21pc2U8Ym9vbGVhbj47XG4gICAgLyoqXG4gICAgICogUmVhZHMgYXV0b21hdGljYWxseSBmYWxsIGJhY2sgYWNyb3NzIHRoZSByZWR1bmRhbnQgc291cmNlcyB1bmxlc3MgY29uZmlnLm5vRmFsbGJhY2tzIGlzIHNldC5cbiAgICAgKiBBIGZhbGxiYWNrIGNvcHkgY2FuIGxhZyB0aGUgd3JpdGUgdGFyZ2V0LCBzbyBhIGNhbGxlciByZWFkaW5nIHN0YXRlIGluIG9yZGVyIHRvIG11dGF0ZSBpdFxuICAgICAqIChlLmcuIHgrKyksIHdoZXJlIGFjdGluZyBvbiBwcmV2aW91cyBzdGF0ZSB3b3VsZCBjYXVzZSBiaWcgaXNzdWVzLCBzaG91bGQgcGFzcyBub0ZhbGxiYWNrcyAtXG4gICAgICogYW5kIHRyeS9jYXRjaCB0aGUgcmVhZCwgaGFuZGxpbmcgdGhlIGNhdGNoIGNhc2UgKGEgZG93biBwcmltYXJ5IGlzIHJldHJpZWQgZm9yIGEgd2hpbGUsIHRoZW5cbiAgICAgKiB0aHJvd3MgaW5zdGVhZCBvZiBkZWdyYWRpbmcgdG8gYSBzdGFsZSBjb3B5KS5cbiAgICAgKi9cbiAgICBnZXQoZmlsZU5hbWU6IHN0cmluZywgY29uZmlnPzogR2V0Q29uZmlnKTogUHJvbWlzZTxCdWZmZXIgfCB1bmRlZmluZWQ+O1xuICAgIC8qKiBTZWUgZ2V0IGZvciB0aGUgZmFsbGJhY2sgc2VtYW50aWNzIChhbmQgd2hlbiB0byBwYXNzIG5vRmFsbGJhY2tzKS4gdXJsIGlzIHRoZSBjb25maWcgVVJMIG9mIHRoZSBzb3VyY2UgdGhhdCBhbnN3ZXJlZCAtIHRoZSBhdXRob3JpdHkgdGhlIGRhdGEgKG9yIHRoZSBcImRvZXMgbm90IGV4aXN0XCIpIGNhbWUgZnJvbS4gTXVsdGktc291cmNlIGltcGxlbWVudGF0aW9ucyAoQXJjaGl2ZXNDaGFpbikgQUxXQVlTIHJldHVybiBhbiBvYmplY3Q6IHdoZW4gdGhlIHZhbHVlIGRvZXNuJ3QgZXhpc3QgdGhlcmUgaXMgc3RpbGwgYSBzZXJ2ZXIgc2F5aW5nIGl0IGRvZXNuJ3QgZXhpc3QsIHNvIHRoZXkgcmV0dXJuIHsgdXJsIH0gYWxvbmUgcmF0aGVyIHRoYW4gdW5kZWZpbmVkLiBTaW5nbGUtc291cmNlIGJhY2tlbmRzIHJldHVybiB1bmRlZmluZWQgZm9yIGFic2VudCAodGhleSBBUkUgdGhlIGF1dGhvcml0eSkuICovXG4gICAgZ2V0MihmaWxlTmFtZTogc3RyaW5nLCBjb25maWc/OiBHZXRDb25maWcpOiBQcm9taXNlPHsgZGF0YTogQnVmZmVyOyB3cml0ZVRpbWU6IG51bWJlcjsgc2l6ZTogbnVtYmVyOyB1cmw/OiBzdHJpbmcgfSB8IHsgZGF0YT86IHVuZGVmaW5lZDsgd3JpdGVUaW1lPzogdW5kZWZpbmVkOyBzaXplPzogdW5kZWZpbmVkOyB1cmw6IHN0cmluZyB9IHwgdW5kZWZpbmVkPjtcbiAgICAvKipcbiAgICAgKiBsYXN0TW9kaWZpZWQgc3RhbXBzIHRoZSB3cml0ZSB3aXRoIHRoYXQgbGFzdC13cml0ZSB0aW1lIGluc3RlYWQgb2Ygbm93LiBJZiBpdCBpcyBPTERFUiB0aGFuXG4gICAgICogdGhlIGZpbGUncyBjdXJyZW50IGxhc3Qtd3JpdGUgdGltZSB0aGUgd3JpdGUgbm8tb3BzIChzbyBkZWxheWVkIC8gc3luY2hyb25pemVkIHdyaXRlcyBjYW5cbiAgICAgKiBuZXZlciBjbG9iYmVyIG5ld2VyIGRhdGEpLiBUaW1lcyBtb3JlIHRoYW4gMTUgbWludXRlcyBpbiB0aGUgZnV0dXJlIGFyZSByZWplY3RlZC5cbiAgICAgKlxuICAgICAqIFJldHVybnMgdGhlIGZ1bGwga2V5IGFjdHVhbGx5IHdyaXR0ZW4gLSBpZGVudGljYWwgdG8gZmlsZU5hbWUsIEVYQ0VQVCBmb3Iga2V5cyBjb250YWluaW5nXG4gICAgICogVkFSSUFCTEVfU0hBUkQsIHdoZXJlIHRoZSBzaGFyZCB2YWx1ZSBpcyBtYXRlcmlhbGl6ZWQgaW50byB0aGUga2V5IChwaWNrZWQgYnkgc2hhcmQgbGF0ZW5jeSxcbiAgICAgKiBzZWUgQXJjaGl2ZXNDaGFpbikgYW5kIHRoZSBjYWxsZXIgbmVlZHMgdGhlIHJldHVybmVkIGtleSB0byBldmVyIHJlYWQgdGhlIHZhbHVlIGJhY2suXG4gICAgICovXG4gICAgLyoqXG4gICAgICogVEhST1dTIG9uIGFuIGVtcHR5IGJ1ZmZlcjogYW4gZW1wdHkgZmlsZSBJUyBhIGRlbGV0aW9uIGluIHRoaXMgc3lzdGVtICh0aGUgdG9tYnN0b25lKSwgc28gYVxuICAgICAqIHNldC1lbXB0eSB3b3VsZCByZWFkIGJhY2sgYXMgXCJ0aGUgZmlsZSBpcyBnb25lXCIgLSB3aGljaCBpcyBqdXN0IGFza2luZyBmb3IgcHJvYmxlbXMuIElmIHlvdVxuICAgICAqIHdhbnQgdGhlIGZpbGUgZGVsZXRlZCwgY2FsbCBkZWw7IGRlbGV0aW9ucyB0YWtlIHRoZWlyIG93biBwYXRoLlxuICAgICAqL1xuICAgIHNldChmaWxlTmFtZTogc3RyaW5nLCBkYXRhOiBCdWZmZXIsIGNvbmZpZz86IFNldENvbmZpZyk6IFByb21pc2U8c3RyaW5nPjtcbiAgICBkZWwoZmlsZU5hbWU6IHN0cmluZywgY29uZmlnPzogRGVsQ29uZmlnKTogUHJvbWlzZTx2b2lkPjtcbiAgICAvKiogTW92ZXMgYSBmaWxlIHRvIGEgbmV3IHBhdGggd2l0aGluIFRISVMgYXJjaGl2ZXMsIGJhY2tlbmQtc2lkZSB3aGVyZSB0aGUgYmFja2VuZCBjYW4gKGJhY2tibGF6ZSBjb3BpZXMgc2VydmVyLXNpZGUsIGRpc2sgcmVuYW1lcywgdGhlIHN0b3JhZ2Ugc2VydmVyIHJlbG9jYXRlcyBub2RlLXNpZGUpIC0gdGhlIGJ5dGVzIG5ldmVyIHRyYXZlbCB0aHJvdWdoIHRoZSBjYWxsZXIuIFRoZSBkZXN0aW5hdGlvbiBpcyBzdGFtcGVkIHdpdGggYSBGUkVTSCB3cml0ZSB0aW1lLCBldmVuIHdoZW4gdGhlIHVuZGVybHlpbmcgb3BlcmF0aW9uIChhIHJlbmFtZSkgd291bGQgcHJlc2VydmUgdGhlIG9sZCBvbmUsIHNvIHRoZSBtb3ZlZCBmaWxlIGNhbm5vdCBpbW1lZGlhdGVseSBsb3NlIHRvIHNvbWV0aGluZyBuZXdlciBzaXR0aW5nIGF0IGl0cyBuZXcgcGF0aCAoZS5nLiB0aGUgdG9tYnN0b25lIG9mIGFuIGVhcmxpZXIgZGVsZXRpb24gdGhlcmUpOyB0aGUgc291cmNlIGlzIHRoZW4gZGVsZXRlZCwgZXhhY3RseSBsaWtlIGRlbC4gVEhST1dTIHdoZW4gdGhlIHNvdXJjZSBmaWxlIGRvZXMgbm90IGV4aXN0LiBPcHRpb25hbCAtIGNhbGxlcnMgZ28gdGhyb3VnaCBtb3ZlQXJjaGl2ZUZpbGUgKGFyY2hpdmVIZWxwZXJzLnRzKSwgd2hpY2ggZmFsbHMgYmFjayB0byBjb3B5ICsgY29uZmlybSArIGRlbGV0ZS4gKi9cbiAgICBtb3ZlPyhjb25maWc6IE1vdmVGaWxlQ29uZmlnKTogUHJvbWlzZTx2b2lkPjtcbiAgICAvKiogUmVzdG9yZXMgYSBkZWxldGVkIGZpbGUgd2hvc2UgYnl0ZXMgYXJlIHN0aWxsIGluIHRoZSBkZWxldGlvbiBoaXN0b3J5IChzZWUgU2V0Q29uZmlnLnVuZGVsZXRlLCB3aGljaCB0aGlzIHJpZGVzIG9uKS4gT25seSBpbmRleC1iYWNrZWQgc3RvcmVzIGtlZXAgYSBkZWxldGlvbiBoaXN0b3J5LCBzbyBvbmx5IHRoZXkgc3VwcG9ydCB0aGlzLiBUSFJPV1Mgd2hlbiB0aGVyZSBpcyBub3RoaW5nIHRvIHJlc3RvcmUuICovXG4gICAgdW5kZWxldGU/KGZpbGVOYW1lOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+O1xuICAgIC8qKiBTdHJlYW1zIGEgZmlsZSB0b28gbGFyZ2UgdG8gaG9sZCBpbiBtZW1vcnkuIGdldE5leHREYXRhIHJldHVybnMgdW5kZWZpbmVkIHdoZW4gZG9uZS4gVGhpcyBvbmx5IG5lZWRzIHRvIGJlIGNhbGxlZCB3aGVuIHlvdSBDQU5OT1QgbWF0ZXJpYWxpemUgdGhlIGVudGlyZSBmaWxlIGluIG1lbW9yeSAtIGlmIHlvdSBjYW4sIGp1c3QgY2FsbCBzZXQ6IGFib3ZlIExBUkdFX1NFVF9USFJFU0hPTEQgaXQgc3RyZWFtcyB0aHJvdWdoIHNldExhcmdlRmlsZSBpbnRlcm5hbGx5LCBrZWVwaW5nIHRoZSBjbGllbnQgcmVzcG9uc2l2ZSBhbmQgbm90IG92ZXJ3aGVsbWluZyB0aGUgc2VydmVyLiBUaGUgcmVzdCBvZiB0aGUgY29uZmlnIGlzIGEgcGxhaW4gU2V0Q29uZmlnIGFuZCBtZWFucyBleGFjdGx5IHdoYXQgaXQgbWVhbnMgb24gc2V0ICh0aGF0IGlzIHdoYXQgbWFrZXMgYSBsYXJnZSBzZXQgYmVoYXZlIGxpa2UgYSBzbWFsbCBvbmUgaW5zdGVhZCBvZiBxdWlldGx5IGxvc2luZyBpbW11dGFiaWxpdHksIG9yZGVyaW5nLCBpbnRlcm5hbCwgb3IgZmFsbGJhY2tzIHNlbWFudGljcyBhcyB0aGUgZmlsZSBjcm9zc2VzIHRoZSB0aHJlc2hvbGQpOyBiYWNrZW5kcyB0aGF0IHN0YW1wIHRoZWlyIG93biB0aW1lcyAoYmFja2JsYXplKSBhY2NlcHQgYW5kIGlnbm9yZSBsYXN0TW9kaWZpZWQuIFRIUk9XUyB3aGVuIHRoZSBzdHJlYW0gcHJvZHVjZXMgbm8gZGF0YSBhdCBhbGwgLSBzYW1lIHJ1bGUgYXMgc2V0OiBhbiBlbXB0eSBmaWxlIElTIGEgZGVsZXRpb24gYW5kIHdvdWxkIHJlYWQgYmFjayBhcyBtaXNzaW5nLiAqL1xuICAgIHNldExhcmdlRmlsZShjb25maWc6IFNldExhcmdlRmlsZUNvbmZpZyk6IFByb21pc2U8dm9pZD47XG4gICAgLyoqIHdyaXRlVGltZSBpcyB0aGUgbGFzdC13cml0ZSB0aW1lIOKAlCBzZWUgQXJjaGl2ZUZpbGVJbmZvLmNyZWF0ZVRpbWUsIHdoaWNoIGlzIHRoZSBzYW1lIHZhbHVlLiB1cmwgYXMgaW4gZ2V0Mi4gU2l6ZS0wIGVudHJpZXMgKHRvbWJzdG9uZXMpIHJlcG9ydCB1bmRlZmluZWQgdW5sZXNzIGNvbmZpZy5pbmNsdWRlVG9tYnN0b25lcy4gKi9cbiAgICBnZXRJbmZvKGZpbGVOYW1lOiBzdHJpbmcsIGNvbmZpZz86IEdldEluZm9Db25maWcpOiBQcm9taXNlPHsgd3JpdGVUaW1lOiBudW1iZXI7IHNpemU6IG51bWJlcjsgdXJsPzogc3RyaW5nIH0gfCB1bmRlZmluZWQ+O1xuICAgIC8qKlxuICAgICAqIEVtcHR5IChzaXplLTApIGZpbGVzIGFyZSBORVZFUiByZXR1cm5lZCBieSBpbmRleC1iYWNrZWQgc3RvcmVzIChCbG9iU3RvcmUsIGFuZCB0aGVyZWZvcmUgdGhlXG4gICAgICogY2hhaW4pOiBhbiBlbXB0eSBmaWxlIElTIGEgbWlzc2luZyBmaWxlIC0gdGhlIHRvbWJzdG9uZSBvZiBhIGRlbGV0aW9uLiBJZiB5b3Ugd2FudCBhIG1hcmtlclxuICAgICAqIGZpbGUgdGhhdCBzaG93cyB1cCBpbiBsaXN0aW5ncywgYWRkIHNvbWUgY29udGVudCB0byBpdC4gUmF3IHNvdXJjZXMgKGRpc2ssIGJhY2tibGF6ZSkgRE8gbGlzdFxuICAgICAqIHRoZWlyIGVtcHR5IGZpbGVzIC0gdGhhdCBpcyBob3cgc2NhbnMgbGVhcm4gb2YgZGVsZXRpb25zIC0gYnV0IG5vdGhpbmcgYnVpbHQgb24gdGhlIGluZGV4XG4gICAgICogZXZlciBzdXJmYWNlcyB0aGVtLlxuICAgICAqL1xuICAgIGZpbmQocHJlZml4OiBzdHJpbmcsIGNvbmZpZz86IEZpbmRDb25maWcpOiBQcm9taXNlPHN0cmluZ1tdPjtcbiAgICAvKiogU2VlIGZpbmQgZm9yIHRoZSBlbXB0eS1maWxlICh0b21ic3RvbmUpIHJ1bGUuICovXG4gICAgZmluZEluZm8ocHJlZml4OiBzdHJpbmcsIGNvbmZpZz86IEZpbmRDb25maWcpOiBQcm9taXNlPEFyY2hpdmVGaWxlSW5mb1tdPjtcbiAgICAvKiogT25seSB3b3JrcyBmb3IgcHVibGljIGJ1Y2tldHMgKHByaXZhdGUgYnVja2V0cyBhcmUgQVBJLWFjY2VzcyBvbmx5KS4gKi9cbiAgICBnZXRVUkwocGF0aDogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmc+O1xuICAgIC8qKiBUaGUgYnVja2V0J3MgY29uZmlndXJhdGlvbiwgd2hpY2ggdGVsbHMgd2hldGhlciB0aGUgb3B0aW9uYWwgZnVuY3Rpb25zIGFyZSBzdXBwb3J0ZWQuICovXG4gICAgZ2V0Q29uZmlnKCk6IFByb21pc2U8QXJjaGl2ZXNDb25maWc+O1xuICAgIC8qKlxuICAgICAqIEFsbCBmaWxlcyBjaGFuZ2VkIGFmdGVyIGNvbmZpZy50aW1lLCBvcHRpb25hbGx5IHJlc3RyaWN0ZWQgdG8ga2V5cyByb3V0aW5nIGludG8gb25lIG9mXG4gICAgICogY29uZmlnLnJvdXRlcyAodXNlZCBieSBzY2FubmluZywgc28gcGFydGlhbGx5LW92ZXJsYXBwaW5nIHNoYXJkcyBvbmx5IHJlY2VpdmUgdGhlaXIgc2xpY2UpLlxuICAgICAqIFdoZW4gZ2V0Q29uZmlnKCkuc3VwcG9ydHNDaGFuZ2VzQWZ0ZXIsIHRoaXMgaXMgYmFja2VkIGJ5IGFuIGluZGV4IChmYXN0LCBhbmQgZGVsZXRpb25zIEFSRVxuICAgICAqIHJlcG9ydGVkLCBhcyBzaXplLTAgdG9tYnN0b25lIGVudHJpZXMpLiBFdmVyeSBvdGhlciBiYWNrZW5kIGVtdWxhdGVzIGl0OiBhIGZ1bGwgZmluZEluZm9cbiAgICAgKiBsaXN0aW5nIGZpbHRlcmVkIGluIG1lbW9yeSAtIGNvcnJlY3QsIGJ1dCBubyBjaGVhcGVyIHRoYW4gdGhlIGxpc3RpbmcgaXRzZWxmLlxuICAgICAqL1xuICAgIGdldENoYW5nZXNBZnRlcjIoY29uZmlnOiBDaGFuZ2VzQWZ0ZXJDb25maWcpOiBQcm9taXNlPEFyY2hpdmVGaWxlSW5mb1tdPjtcbiAgICAvKiogU3luY2hyb25pemF0aW9uIGludHJvc3BlY3Rpb24sIGZvciBiYWNrZW5kcyB0aGF0IHN5bmNocm9uaXplIGZyb20gc291cmNlcyAoc2VlIEJsb2JTdG9yZSkuICovXG4gICAgZ2V0U3luY1N0YXR1cz8oKTogUHJvbWlzZTxBcmNoaXZlc1N5bmNTdGF0dXM+O1xufVxuIl19
62
- /* _JS_SOURCE_HASH = "9977b7c04e7bbb7d56b14b981ed0fe4d385af18d0919bbc8a458f567da000f2a"; */
61
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiSUFyY2hpdmVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiSUFyY2hpdmVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSx3S0FBd0s7OztBQUV4SyxzSkFBc0o7QUFDekksUUFBQSx3QkFBd0IsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQUV2RCx5TEFBeUw7QUFDNUssUUFBQSxvQkFBb0IsR0FBRyxLQUFLLEdBQUcsSUFBSSxDQUFDO0FBQ2pELFNBQWdCLHVCQUF1QixDQUFDLFlBQW9CO0lBQ3hELElBQUksR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxnQ0FBd0IsQ0FBQztJQUNoRCxJQUFJLFlBQVksR0FBRyxHQUFHLEVBQUUsQ0FBQztRQUNyQixNQUFNLElBQUksS0FBSyxDQUFDLDBDQUEwQyxZQUFZLE1BQU0sR0FBRyxxQkFBcUIsQ0FBQyxDQUFDO0lBQzFHLENBQUM7QUFDTCxDQUFDO0FBTEQsMERBS0M7QUF1RlksUUFBQSxpQkFBaUIsR0FBcUIsQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUM7QUE0SWhGLHdYQUF3WDtBQUMzVyxRQUFBLDBCQUEwQixHQUFHLDRDQUE0QyxDQUFDO0FBRXZGLDhMQUE4TDtBQUNqTCxRQUFBLG1CQUFtQixHQUFHLHFDQUFxQyxDQUFDO0FBRXpFLHVXQUF1VztBQUMxVixRQUFBLHNCQUFzQixHQUFHLHdDQUF3QyxDQUFDO0FBRWxFLFFBQUEsVUFBVSxHQUFxQixDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUVuRCwyUkFBMlI7QUFDOVEsUUFBQSxjQUFjLEdBQUcsNkNBQTZDLENBQUM7QUFDNUUsb0xBQW9MO0FBQ3BMLDhKQUE4SjtBQUM5SixTQUFnQixtQkFBbUIsQ0FBQyxXQUF5QztJQUN6RSxJQUFJLENBQUMsV0FBVztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQzlCLE9BQU8sV0FBVyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztBQUN2QyxDQUFDO0FBSEQsa0RBR0M7QUFDRCxpTkFBaU47QUFDak4sU0FBZ0IsbUJBQW1CLENBQUMsWUFBZ0M7SUFDaEUsT0FBTyxZQUFZLENBQUMsSUFBSSxDQUFDLG1CQUFtQixDQUFDLENBQUM7QUFDbEQsQ0FBQztBQUZELGtEQUVDO0FBRUQsd0tBQXdLO0FBQzNKLFFBQUEsbUJBQW1CLEdBQUcsQ0FBQyxHQUFHLElBQUksR0FBRyxJQUFJLENBQUM7QUFFbkQsbVJBQW1SO0FBQ25SLFNBQWdCLGlCQUFpQixDQUFDLElBQVk7SUFDMUMsSUFBSSxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ2YsT0FBTztRQUNILFdBQVcsRUFBRSxLQUFLLElBQUksRUFBRTtZQUNwQixJQUFJLE1BQU0sSUFBSSxJQUFJLENBQUMsTUFBTTtnQkFBRSxPQUFPLFNBQVMsQ0FBQztZQUM1QyxJQUFJLEtBQUssR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxNQUFNLEdBQUcsMkJBQW1CLENBQUMsQ0FBQztZQUNoRSxNQUFNLElBQUksS0FBSyxDQUFDLE1BQU0sQ0FBQztZQUN2QixPQUFPLEtBQUssQ0FBQztRQUNqQixDQUFDO1FBQ0QsYUFBYSxFQUFFLEdBQUcsRUFBRTtZQUNoQixNQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQ2YsQ0FBQztLQUNKLENBQUM7QUFDTixDQUFDO0FBYkQsOENBYUM7QUFFRCx3SkFBd0o7QUFDeEosbURBQW1EO0FBQTFDLGlIQUFBLGVBQWUsT0FBQSIsInNvdXJjZXNDb250ZW50IjpbIi8vIFRoZSBpbXBvcnRhbnQgb3BlcmF0aW9ucyBvZiBhbiBhcmNoaXZlIGJ1Y2tldCAoZXh0cmFjdGVkIGZyb20gQXJjaGl2ZXNCYWNrYmxhemUpLCBzbyBvdGhlciBiYWNrZW5kcyAoZS5nLiBvdXIgb3duIHJlbW90ZSBzdG9yYWdlIHNlcnZlcikgY2FuIGJlIHVzZWQgaW50ZXJjaGFuZ2VhYmx5LlxuXG4vLyBBIHdyaXRlIG1heSBub3QgYmUgc3RhbXBlZCBtb3JlIHRoYW4gdGhpcyBmYXIgaW4gdGhlIGZ1dHVyZSwgb3IgY2xvY2sgc2tldyBiZXR3ZWVuIG1hY2hpbmVzIHdvdWxkIGxldCBhIGJhZCB0aW1lc3RhbXAgYmxvY2sgd3JpdGVzIGZvciBhIGxvbmcgdGltZS5cbmV4cG9ydCBjb25zdCBNQVhfTEFTVF9NT0RJRklFRF9GVVRVUkUgPSAxNSAqIDYwICogMTAwMDtcblxuLy8gSG93IGxvbmcgYnJvd3NlcnMgbWF5IGNhY2hlIGZpbGVzIGZyb20gaW1tdXRhYmxlIGJ1Y2tldHMgKHRoZSBDYWNoZS1Db250cm9sIG1heC1hZ2UpLCBzaGFyZWQgYnkgZXZlcnkgaG9zdGluZyBwYXRoIChiYWNrYmxhemUgYnVja2V0IHNldHRpbmdzIGFuZCBvdXIgb3duIHN0b3JhZ2Ugc2VydmVyJ3MgSFRUUCByb3V0ZSlcbmV4cG9ydCBjb25zdCBJTU1VVEFCTEVfQ0FDSEVfVElNRSA9IDg2NDAwICogMTAwMDtcbmV4cG9ydCBmdW5jdGlvbiBhc3NlcnRWYWxpZExhc3RNb2RpZmllZChsYXN0TW9kaWZpZWQ6IG51bWJlcik6IHZvaWQge1xuICAgIGxldCBtYXggPSBEYXRlLm5vdygpICsgTUFYX0xBU1RfTU9ESUZJRURfRlVUVVJFO1xuICAgIGlmIChsYXN0TW9kaWZpZWQgPiBtYXgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBsYXN0TW9kaWZpZWQgaXMgdG9vIGZhciBpbiB0aGUgZnV0dXJlOiAke2xhc3RNb2RpZmllZH0gPiAke21heH0gKG5vdyArIDE1IG1pbnV0ZXMpYCk7XG4gICAgfVxufVxuXG5cbmV4cG9ydCB0eXBlIFJlbW90ZUNvbmZpZyA9IHtcbiAgICAvLyBOT1RFOiBWZXJzaW9uIGlzIHVzZWQgd2hlbiB1cGRhdGluZyB0aGUgY29uZmlndXJhdGlvbi4gVGhlIG5ld2VyIHZlcnNpb24gaXMgYWx3YXlzIHRha2VuLiBBIG1pc3NpbmcgdmVyc2lvbiBjb3VudHMgYXMgdmVyc2lvbiAtMS5cbiAgICB2ZXJzaW9uPzogbnVtYmVyO1xuICAgIHNvdXJjZXM6IFJlbW90ZUNvbmZpZ0Jhc2VbXTtcbn07XG5cbi8qKlxuICAgIHN0cmluZyBhcmd1bWVudHMgd2lsbCBiZSBhIHVybCwgbG9va2luZyBsaWtlOlxuICAgICAgICBodHRwczovL3N0b3JhZ2UyLnZpZGdyaWR3ZWIuY29tOjQ0NDUvZmlsZS9leGFtcGxlYWNjb3VudC9leGFtcGxlYnVja2V0L3N0b3JhZ2Uvc3RvcmFnZXJvdXRpbmcuanNvblxuICAgICAgICBodHRwczovL2YwMDIuYmFja2JsYXplYjIuY29tL2ZpbGUvcXVlcnlzdWJ0ZXN0LWNvbS1wdWJsaWMtaW1tdXRhYmxlL3N0b3JhZ2Uvc3RvcmFnZXJvdXRpbmcuanNvblxuICAgICAgICAtIFRoZXNlIG1hcCB0byB7IHVybCB9LCB3aXRoIHRoZSB0eXBlIGluZmVycmVkIGZyb20gdGhlIHVybFxuICAgICAgICAtIEhvc3RlZCB1cmxzIGFyZSAvZmlsZS88YWNjb3VudD4vPGJ1Y2tldE5hbWU+Ly4uLiwgYmFja2JsYXplIHVybHMgYXJlIC9maWxlLzxidWNrZXROYW1lPi8uLi5cblxuICAgIE5PVEU6IElmIHdlIGRvIG5vdCBoYXZlIHJpZ2h0IGFjY2VzcyB0byB0aGVzZSwgdGhlbiBpdCBiZWNvbWVzIGEgcmVhZC1vbmx5IElBcmNoaXZlcywgd2hlcmUgd2Ugc29sZWx5IHJlYWQgdXNpbmcgdGhlIHVybCBmb3JtICh3aGljaCBtaWdodCB0aHJvdyBkdWUgdG8gbm90IGhhdmluZyBhY2Nlc3MgYXMgd2VsbCkuIFVOTEVTUyBPdXIgY29uZmlndXJhdGlvbiBleHBsaWNpdGx5IGhhcyBwdWJsaWM6IGZhbHNlLCBpbiB3aGljaCBjYXNlLCB3ZSBkb24ndCBldmVuIGhpdCB0aGUgVVJMIGFuZCB3ZSB0aHJvdyBvbiBhY2Nlc3MuXG5cbiAgICBOT1RFOiBJZiB3ZSdyZSBpbiB0aGUgYnJvd3Nlciwgd2Ugc2hvdWxkIGFsbG93IGRvd25sb2FkaW5nIHRoZSBmaWxlcyB2aWEgdGhlIFVSTCBmb3JtIChpZiBpdCdzIGEgcHVibGljIGJ1Y2tldCksIGhvd2V2ZXIsIHdlIHdvbid0IGFsbG93IHdyaXRpbmcsIGJlY2F1c2UgdGhlaXIgc2VydmVycyBkbyBub3QgYWxsb3cgc2VjdXJlIGJyb3dzZXIgd3JpdGVzLlxuKi9cbmV4cG9ydCB0eXBlIFJlbW90ZUNvbmZpZ0Jhc2UgPSBzdHJpbmcgfCBTb3VyY2VDb25maWc7XG5cbi8qKiBPbmUgY29uZmlndXJlZCBzb3VyY2UgaW4gYSByb3V0aW5nIGNvbmZpZzogYSBob3N0ZWQgKG91ciBzdG9yYWdlIHNlcnZlcikgb3IgYmFja2JsYXplIGVudHJ5LiBSZXF1ZXN0cyBjYXJyeSB0aGUgZXhhY3QgU291cmNlQ29uZmlnIHRoZXkgc2VsZWN0ZWQsIGFuZCB0aGUgc2VydmVyIG1hdGNoZXMgaXQgYWdhaW5zdCBpdHMgb3duIGVudHJpZXMgdG8gcGljayB0aGUgYmFja2luZyBzdG9yZS4gKi9cbmV4cG9ydCB0eXBlIFNvdXJjZUNvbmZpZyA9IEhvc3RlZENvbmZpZyB8IEJhY2tibGF6ZUNvbmZpZztcblxuZXhwb3J0IHR5cGUgQ29tbW9uQ29uZmlnID0ge1xuICAgIC8qKlxuICAgICAqIFRoZSBzdG9yYWdlIHRoaXMgZW50cnkgbmFtZXMsIGFzIG9wcG9zZWQgdG8gdGhlIHJ1bGVzIGZvciB1c2luZyBpdC4gRXZlcnkgZW50cnkgd2l0aCB0aGUgc2FtZVxuICAgICAqIG5hbWUgKGZvciB0aGUgc2FtZSBhY2NvdW50IGFuZCBidWNrZXQpIElTIHRoZSBzYW1lIHN0b3JhZ2U6IG9uZSBmb2xkZXIgb24gdGhlIHNlcnZlciwgb25lXG4gICAgICogc3RvcmUsIG9uZSBpbmRleCAtIGhvd2V2ZXIgbWFueSBlbnRyaWVzIHRoZXJlIGFyZSBhbmQgd2hhdGV2ZXIgdGhlaXIgd2luZG93cyBhbmQgcm91dGVzIHNheS5cbiAgICAgKiBFdmVyeXRoaW5nIGFib3V0IFdIRU4gYW5kIFdISUNIIEtFWVMgKHZhbGlkV2luZG93LCByb3V0ZSkgaXMgcG9saWN5IGxheWVyZWQgb24gdG9wIG9mIGl0LCBhbmRcbiAgICAgKiBjaGFuZ2luZyB0aGF0IHBvbGljeSBuZXZlciBtb3ZlcyBkYXRhLlxuICAgICAqXG4gICAgICogTGV0dGVycywgbnVtYmVycywgdW5kZXJzY29yZSwgZGFzaCBhbmQgcGVyaW9kcywgdXAgdG8gNjQgY2hhcmFjdGVycyAtIHNvIGEgaG9zdCBvciBhIHZlcnNpb25cbiAgICAgKiBjYW4gYmUgdXNlZCBhcy1pcy4gSXQgaXMgdGhlIGZvbGRlciBuYW1lLCBzbyBpdCBtdXN0IHN0YXkgdW5pcXVlIGFuZCBtdXN0IG5ldmVyIGJlIHJldXNlZCBmb3JcbiAgICAgKiBkaWZmZXJlbnQgc3RvcmFnZTpcbiAgICAgKiBwb2ludGluZyB0d28gdW5yZWxhdGVkIGVudHJpZXMgYXQgb25lIG5hbWUgbWVyZ2VzIHRoZWlyIGRhdGEsIGFuZCByZS11c2luZyBhIHJldGlyZWQgbmFtZVxuICAgICAqIGhhbmRzIHRoZSBuZXcgZW50cnkgdGhlIHJldGlyZWQgb25lJ3MgZmlsZXMuIERlY2lkaW5nIHRoYXQgaXMgdGhlIGRldmVsb3BlcidzIGpvYiAtIHRoZSBzZXJ2ZXJcbiAgICAgKiBvbmx5IGV2ZXIgZG9lcyB3aGF0IHRoZSBuYW1lIHNheXMuXG4gICAgICovXG4gICAgbmFtZTogc3RyaW5nO1xuICAgIC8qKiBCeSBkZWZhdWx0IGEgc2VydmVyIGhvc3RpbmcgdGhpcyBidWNrZXQgZWFnZXJseSBjb3BpZXMgdGhpcyBzb3VyY2UncyBmdWxsIGNvbnRlbnRzIG9udG8gaXRzIG93biBkaXNrIChvbiB0b3Agb2YgdGhlIGxhenkgcmVhZC10aHJvdWdoIGNhY2hpbmcpLiBTZXQgdGhpcyB0byBiZSBhIGZyb250IGVuZCBmb3IgYSB2ZXJ5IGxhcmdlIGRhdGFiYXNlIHdpdGhvdXQgY29weWluZyB0aGUgZnVsbCBkYXRhYmFzZSAtIHJlYWRzIHN0aWxsIGRvd24tY2FjaGUgaW5kaXZpZHVhbCBmaWxlcyBvbiBkZW1hbmQuICovXG4gICAgbm9GdWxsU3luYz86IGJvb2xlYW47XG4gICAgLyoqIEJ5dGVzIG9mIHJlYWQtY2FjaGUgdGhpcyBzZXJ2ZXIncyBkaXNrIG1heSBob2xkOyBsZWFzdC1yZWNlbnRseS11c2VkIGZpbGVzIGFyZSBkZWxldGVkIGZyb20gZGlzayB0byBzdGF5IHVuZGVyIGl0IChvbmx5IGV2ZXIgd2hlbiBhbm90aGVyIHNvdXJjZSB2ZXJpZmlhYmx5IGhvbGRzIHRoZSBmaWxlIC0gdGhlIG9ubHkgY29weSBpcyBuZXZlciBkZWxldGVkKS4gUmVxdWlyZXMgbm9GdWxsU3luYyAoYSBmdWxsIGNvcHkgY2FuJ3QgYmUgYm91bmRlZCkuICovXG4gICAgcmVhZGVyRGlza0xpbWl0PzogbnVtYmVyO1xuICAgIC8qKiBUaGUgd3JpdGUgdGltZXMgKFtzdGFydE1zLCBlbmRNc10pIHRoaXMgc291cmNlIGlzIHZhbGlkIGZvciAoc2VlIEFyY2hpdmVzU291cmNlLnZhbGlkV2luZG93IGZvciB0aGUgc3luY2hyb25pemF0aW9uIHNlbWFudGljcykuIFJlcXVpcmVkIG9uIG9iamVjdCBjb25maWdzOiBjb25maWd1cmF0aW9uIGNoYW5nZXMgbXVzdCBiZSBTQ0hFRFVMRUQgKGEgbmV3IHNvdXJjZSBiZWNvbWVzIHZhbGlkIGF0IGEgZnV0dXJlIHRpbWUgd2hpbGUgdGhlIG9sZCBvbmUncyB3aW5kb3cgZW5kcyksIG5vdCBmbGlwcGVkIGluc3RhbnRseS4gUGxhaW4gVVJMLXN0cmluZyBzb3VyY2VzIGRlZmF1bHQgdG8gRlVMTF9WQUxJRF9XSU5ET1cgLSBvbmNlIHlvdSdyZSB3cml0aW5nIG9iamVjdCBjb25maWdzLCB5b3UncmUgZG9pbmcgc29tZXRoaW5nIGNvbXBsaWNhdGVkIGVub3VnaCB0byB0aGluayBhYm91dCB3aGVuIHRoaW5ncyBjaGFuZ2UuICovXG4gICAgdmFsaWRXaW5kb3c6IFtudW1iZXIsIG51bWJlcl07XG4gICAgLyoqIFNoYXJkaW5nOiB0aGUgZnJhY3Rpb24gb2YgdGhlIGtleSBzcGFjZSB0aGlzIHNvdXJjZSBoYW5kbGVzLCBhcyBbc3RhcnQsIGVuZCkgb3ZlciBbMCwgMSkgKGtleXMgYXJlIHJvdXRlZCBieSBnZXRSb3V0ZSBpbiByZW1vdGVDb25maWcudHMpLiBEZWZhdWx0cyB0byBGVUxMX1JPVVRFICh1bnNoYXJkZWQpLiBBdCBldmVyeSBwb2ludCBpbiB0aW1lIHRoZSBzb3VyY2VzJyByb3V0ZXMgbXVzdCBmdWxseSBjb3ZlciBbMCwgMSksIG9yIHNvbWUga2V5cyBjb3VsZCBuZXZlciBiZSByZWFkLiAqL1xuICAgIHJvdXRlPzogW251bWJlciwgbnVtYmVyXTtcbiAgICAvKiogU2V0IG9uIGVudHJpZXMgaW5qZWN0ZWQgaW50byB0aGUgaW4tbWVtb3J5IGNvbmZpZyBieSBhbiBvdmVybGF5IChhIGRlcGxveSBzd2l0Y2hvdmVyJ3MgYWx0ZXJuYXRlLXBvcnQgd2luZG93KS4gTmV2ZXIgd3JpdHRlbiB0byBkaXNrOiByZXNvbHZlSW50ZXJtZWRpYXRlU291cmNlcyBzdHJpcHMgdGhlc2UgYW5kIHJlam9pbnMgdGhlIHdpbmRvd3MgYXJvdW5kIHRoZW0sIHdoaWNoIGlzIGFsc28gaG93IGEgY2xpZW50IHRlbGxzIHdoZXRoZXIgYW4gdXBkYXRlIGlzIGEgcmVhbCBjb25maWd1cmF0aW9uIGNoYW5nZSBvciBqdXN0IGFuIG92ZXJsYXkuIFRoZSBWQUxVRSBpcyB0aGUgdXJsIG9mIHRoZSBzb3VyY2UgdGhpcyBpbnRlcm1lZGlhdGUgd2FzIHNwbGl0IG91dCBvZiAoaXRzIGFsdGVybmF0ZS1wb3J0IHZpZXcpIC0gc28gYSByZXF1ZXN0IG5hbWluZyB0aGUgaW50ZXJtZWRpYXRlIHN0aWxsIHJlc29sdmVzIHRvIHRoZSBPUklHSU5BTCBzb3VyY2UsIGV2ZW4gYWZ0ZXIgdGhlIGludGVybWVkaWF0ZSByZWpvaW5zIGFuZCB0aGUgZW50cnkgaXMgZ29uZS4gKi9cbiAgICBpbnRlcm1lZGlhdGU/OiBzdHJpbmc7XG59O1xuXG5leHBvcnQgdHlwZSBIb3N0ZWRDb25maWcgPSBDb21tb25Db25maWcgJiB7XG4gICAgdHlwZTogXCJyZW1vdGVcIjtcblxuICAgIC8vIEV4OiBodHRwczovLzk5LTI1MC0xMjQtOTEucXVlcnlzdWJ0ZXN0LmNvbTo1MjMzL2ZpbGUvcm9vdC91bmlxdWVidWNrZXRuYW1lL3N0b3JhZ2Uvc3RvcmFnZXJvdXRpbmcuanNvblxuICAgIC8vIE5PVEU6IFRoZSBhY2NvdW50IGFuZCBidWNrZXQgbmFtZSBhcmUgb2J0YWluZWQgZnJvbSB0aGUgVVJMLlxuICAgIHVybDogc3RyaW5nO1xuXG4gICAgLy8gTk9URTogQXV0aGVudGljYXRpb24gaXMgaGFuZGxlZCBieSBjZXJ0LnRzLCB2aWEgaGF2aW5nIHlvdXIgbWFjaGluZSB0cnVzdGVkIHRvIGFjY2VzcyB0aGlzIGFjY291bnQuIFxuXG4gICAgcHVibGljPzogYm9vbGVhbjtcbiAgICAvLyBGYXN0IG1vZGU6IHRoZSBzZXJ2ZXIgYWNrbm93bGVkZ2VzIHdyaXRlcyBvbmNlIHRoZXkgYXJlIGluIG1lbW9yeSwgZmx1c2hpbmcgdG8gZGlzayBhZnRlciB3cml0ZURlbGF5IChkZWZhdWx0IDUgbWludXRlcykgYW5kIGNvYWxlc2Npbmcgd3JpdGVzIHRvIHRoZSBzYW1lIGZpbGUuIEEgc2VydmVyIGNyYXNoIGxvc2VzIHdyaXRlcyB0aGF0IGhhdmVuJ3QgZmx1c2hlZCB5ZXQuXG4gICAgZmFzdD86IGJvb2xlYW47XG4gICAgd3JpdGVEZWxheT86IG51bWJlcjtcbiAgICAvLyBXcml0ZXMgdG8gcGF0aHMgdGhhdCBhbHJlYWR5IGV4aXN0IGFyZSBkaXNhbGxvd2VkIChkZWxldGVzIHN0aWxsIHdvcmspLlxuICAgIGltbXV0YWJsZT86IGJvb2xlYW47XG59O1xuXG5leHBvcnQgdHlwZSBCYWNrYmxhemVDb25maWcgPSBDb21tb25Db25maWcgJiB7XG4gICAgdHlwZTogXCJiYWNrYmxhemVcIjtcbiAgICAvLyBFeDogaHR0cHM6Ly9mMDAyLmJhY2tibGF6ZWIyLmNvbS9maWxlL3F1ZXJ5c3VidGVzdC1jb20tcHVibGljLWltbXV0YWJsZS9zdG9yYWdlL3N0b3JhZ2Vyb3V0aW5nLmpzb25cbiAgICAvLyBOT1RFOiBUaGUgYnVja2V0IG5hbWUgaXMgb2J0YWluZWQgZnJvbSB0aGUgVVJMLlxuICAgIHVybDogc3RyaW5nO1xuICAgIC8vIFB1YmxpYyBidWNrZXRzIGFyZSBzZXJ2ZWQgb3ZlciBwbGFpbiBIVFRQUyBHRVRzIChnZXRVUkwpLiBQcml2YXRlIGJ1Y2tldHMgYXJlIEFQSS1hY2Nlc3Mgb25seS5cbiAgICBwdWJsaWM/OiBib29sZWFuO1xuICAgIC8vIE5PVEU6IFRoaXMgaXNuJ3QgZW5mb3JjZWQgb24gdGhlIGJhY2tibGF6ZSBsZXZlbCwgc28gdGhpcyBpcyBqdXN0IGEgY2xpZW50LXNpZGUgZ3VhcmFudGVlLiBUaGlzIGNhbiBjaGFuZ2UgaG93IHdlIGNhY2hlIGZpbGVzLlxuICAgIC8vICAtIEJhY2tibGF6ZSBkb2VzIHN1cHBvcnQgaW1tdXRhYmlsaXR5LiBIb3dldmVyLCBhcHBhcmVudGx5LCBvbmNlIHdlIGVuYWJsZSBpdCBvbiBhIGJ1Y2tldCwgd2UgY2FuJ3QgZGlzYWJsZSBpdCwgd2hpY2ggaXMgcmVhbGx5IGJhZCwgYXMgaXQgbWVhbnMgaWYgb3VyIGNvZGUgY291bGQgZXZlciBlbmFibGUgaXQgYW5kIHdlIGFjY2lkZW50YWxseSBlbmFibGUgaXQgb24gYW4gaW1wb3J0YW50IGJ1Y2tldCwgd2UgZXNzZW50aWFsbHkganVzdCBicmlja2VkIHRoYXQgYnVja2V0LiBTbyB3ZSBzaG91bGQgbmV2ZXIgd3JpdGUgYW55IGNvZGUgdGhhdCBldmVyIHRyaWVzIHRvIHVzZSBiYWNrYmxhemUgdG8gbWFrZSB0aGluZ3MgaW1tdXRhYmxlLiBcbiAgICBpbW11dGFibGU/OiBib29sZWFuO1xuICAgIC8vIENPUlMgb3JpZ2lucyBhbGxvd2VkIHRvIGNvbnN1bWUgdGhlIGJ1Y2tldCdzIGZpbGVzIGluIGEgYnJvd3Nlci4gTm90IGEgc2VjdXJpdHkgYm91bmRhcnkgKGFjY2VzcyBpcyBnYXRlZCBieSB0aGUgQVBJIGtleSAvIHNpZ25lZCBVUkxzLCBuZWl0aGVyIG9mIHdoaWNoIHJpZGVzIGluIGNvb2tpZXMpIC0gaXQgb25seSBjb250cm9scyB3aGljaCBzaXRlcycgaW4tcGFnZSBKYXZhU2NyaXB0IGNhbiByZWFkIHJlc3BvbnNlcy4gRGVmYXVsdHMgdG8gYW55IEhUVFBTIG9yaWdpbi5cbiAgICBhbGxvd2VkT3JpZ2lucz86IHN0cmluZ1tdO1xuXG4gICAgLy8gTk9URTogV2Ugd2lsbCBhY2Nlc3MgdGhlIGFwaSBrZXkgZnJvbSBnZXRTZWNyZXQsIHNlZSBiYWNrYmxhemUudHMgZm9yIHRoZSBzcGVjaWZpYyBrZXlzLlxufTtcblxuXG5leHBvcnQgY29uc3QgRlVMTF9WQUxJRF9XSU5ET1c6IFtudW1iZXIsIG51bWJlcl0gPSBbMCwgTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVJdO1xuXG5cblxuXG5leHBvcnQgdHlwZSBHZXRDb25maWcgPSB7XG4gICAgcmFuZ2U/OiB7IHN0YXJ0OiBudW1iZXI7IGVuZDogbnVtYmVyIH07XG4gICAgLyoqIFJlYWQgT05MWSBmcm9tIHRoZSBwcmltYXJ5IHNvdXJjZSAtIHRoZSBvbmUgd3JpdGVzIHdvdWxkIHRhcmdldCAtIGluc3RlYWQgb2YgZmFsbGluZyBiYWNrIGFjcm9zcyB0aGUgcmVkdW5kYW50IHNvdXJjZXMuIFVzZSB0aGlzIHdoZW4geW91IHdhbnQgeW91ciByZWFkcyBhbmQgd3JpdGVzIHRvIGJlIHNvbWV3aGF0IGF0b21pYzogdGhlcmUgd2lsbCBzdGlsbCBiZSBpc3N1ZXMgd2l0aCB0aGUgcm91bmQgdHJpcCwgYnV0IHdpdGhvdXQgaXQgeW91IGNvdWxkIHRhbGsgdG8gYSBjb21wbGV0ZWx5IGRpZmZlcmVudCBub2RlIGFuZCBnZXQgYSBtdWNoIG9sZGVyIHZhbHVlLiBNb3N0IHJlYWRzIGFyZW4ndCBmb2xsb3dlZCBieSBhIHdyaXRlIHRob3VnaCwgc28gZm9yIG1vc3QgY2FzZXMgaXQncyBiZXR0ZXIgdG8gZ2V0IGEgdmFsdWUgdGhhbiB0byBoYXZlIHRvIHdhaXQgKG9yIGV2ZW4gdGhyb3cpIHdoZW4gdGhlIHByaW1hcnkgbm9kZSBpcyBub3QgYXZhaWxhYmxlLiAqL1xuICAgIG5vRmFsbGJhY2tzPzogYm9vbGVhbjtcbiAgICAvKiogU3RvcmUtdG8tc3RvcmUgY2FsbDogdGhlIHNlcnZpbmcgbm9kZSBuZXZlciBjb25zdWx0cyBpdHMgT1RIRVIgc291cmNlcyAtIGNoYXNpbmcgaXRzIG93biByZW1vdGUgaG9sZGVycyB3aGlsZSBhbnN3ZXJpbmcgYW5vdGhlciBzdG9yZSBpcyBob3cgaW5maW5pdGUgZ2V0IGxvb3BzIGJldHdlZW4gc3RvcmVzIGZvcm0gKEEgYXNrcyBCLCBCJ3MgaW5kZXggcG9pbnRzIGJhY2sgYXQgQSwgLi4uKS4gVGhhdCBpcyB0aGUgZmxhZydzIEVOVElSRSBtZWFuaW5nOiBubyBmYWxsYmFja3MsIG5vdGhpbmcgZWxzZS4gVGhlIHJlYWQgaXMgb3RoZXJ3aXNlIGZ1bGx5IGNvcnJlY3QgLSB0aGUgbm9kZSdzIGluZGV4IHN0aWxsIGdhdGVzIGl0IChhIGtleSBpdHMgaW5kZXggc2F5cyBpcyBkZWxldGVkIGFuc3dlcnMgYXMgZGVsZXRlZCwgbmV2ZXIgYXMgdGhlIGhpc3RvcnkgYnl0ZXMgc3RpbGwgc2l0dGluZyBvbiBpdHMgZGlzaykuIE5vIHdpbmRvdyBvciByb3V0ZSBjaGVja3Mgb24gcmVhZHMuICovXG4gICAgaW50ZXJuYWw/OiBib29sZWFuO1xuICAgIC8qKiBBbHNvIHJldHVybiBzaXplLTAgcmVzdWx0cyAodG9tYnN0b25lcyAtIGFuIGVtcHR5IGZpbGUgSVMgYSBtaXNzaW5nIGZpbGUpIGluc3RlYWQgb2YgdHJlYXRpbmcgdGhlbSBhcyBhYnNlbnQuIE9mZiBieSBkZWZhdWx0LCBtYXRjaGluZyBnZXRJbmZvJ3MgZmxhZyBvZiB0aGUgc2FtZSBuYW1lLiBTeW5jaHJvbml6YXRpb24gcGFzc2VzIHRoaXMgc28gYSBERUxFVEVEIGZpbGUgKHdpdGggaXRzIHdyaXRlIHRpbWUpIGlzIGRpc3Rpbmd1aXNoYWJsZSBmcm9tIGEgZmlsZSB0aGF0IG5ldmVyIGV4aXN0ZWQuICovXG4gICAgaW5jbHVkZVRvbWJzdG9uZXM/OiBib29sZWFuO1xuICAgIC8qKiBSZWFkcyBmaWxlcyB0aGF0IGFyZSBNQVJLRUQgZm9yIGRlbGV0aW9uIChkZWxldGVkLCBidXQgd2l0aCB0aGVpciBieXRlcyBzdGlsbCBpbiB0aGUgZGVsZXRpb24gaGlzdG9yeSAtIHNlZSBTZXRDb25maWcudW5kZWxldGUgZm9yIHJlc3RvcmluZyB0aGVtKS4gVGhlIGFjdHVhbCBjb250ZW50IGNvbWVzIGJhY2ssIHVubGlrZSBpbmNsdWRlVG9tYnN0b25lcywgd2hpY2ggb25seSByZXBvcnRzIHRoYXQgYSBkZWxldGlvbiBoYXBwZW5lZC4gKi9cbiAgICBpbmNsdWRlTWFya2VkPzogYm9vbGVhbjtcbiAgICAvKiogUmVhZCBmcm9tIEVYQUNUTFkgdGhpcyBzb3VyY2UgLSBpdHMgY29uZmlnIHVybCwgYXMgQXJjaGl2ZXNDaGFpbi5nZXRGaWxlU291cmNlcyBsaXN0cyB0aGVtIC0gd2l0aCBubyBmYWxsYmFjayB0byBhbnkgb3RoZXIuIEZvciBjb21wYXJpbmcgdGhlIGNvcGllcyBkaWZmZXJlbnQgc291cmNlcyBob2xkIChjb21iaW5lIHdpdGggaW50ZXJuYWwgdG8gcmVhZCBvbmx5IHRoYXQgc2VydmVyJ3Mgb3duIGRpc2ssIHNraXBwaW5nIGl0cyBob2xkZXIgcmVzb2x1dGlvbikuIE11bHRpLXNvdXJjZSBhcmNoaXZlcyBvbmx5OyB0aHJvd3Mgd2hlbiBubyBjb25maWd1cmVkIHNvdXJjZSBoYXMgdGhlIHVybC4gKi9cbiAgICBzb3VyY2VVcmw/OiBzdHJpbmc7XG4gICAgLyoqIEhvdyBtYW55IGV4dHJhIHRpbWVzIHRoZSBXSE9MRSBvcGVyYXRpb24gaXMgcmV0cmllZCBhZnRlciBldmVyeSBzb3VyY2UgaW4gYSBwYXNzIGZhaWxlZCAtIGFueSBlcnJvciBjb3VudHMgKHRoZSB3cm9uZy13aW5kb3cvcm91dGUgbWFya2VycyBzdGlsbCBnZXQgdGhlaXIgY29uZmlnIHJlLXJlc29sdmUgZmlyc3QpLiBPbmx5IGFwcGxpZXMgdG8gZmFsbGJhY2sgZGlzcGF0Y2ggKG11bHRpLXNvdXJjZSwgbm90IG5vRmFsbGJhY2tzKSwgd2hlcmUgaXQgZGVmYXVsdHMgdG8gMzsgdGhlIG5vRmFsbGJhY2tzL3dyaXRlLW5vZGUgcGF0aCBhbHJlYWR5IHJldHJpZXMgb24gaXRzIG93biBkZWFkbGluZS4gTXVsdGktcGFydCB1cGxvYWRzIGFkZGl0aW9uYWxseSByZXRyeSBwZXIgcGFydCByZWdhcmRsZXNzIG9mIHRoaXMuICovXG4gICAgcmV0cmllcz86IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIEZpbmRDb25maWcgPSB7XG4gICAgc2hhbGxvdz86IGJvb2xlYW47XG4gICAgdHlwZT86IFwiZmlsZXNcIiB8IFwiZm9sZGVyc1wiO1xuICAgIC8qKiBBbHNvIGxpc3QgZmlsZXMgTUFSS0VEIGZvciBkZWxldGlvbiAoc2VlIEdldENvbmZpZy5pbmNsdWRlTWFya2VkKS4gKi9cbiAgICBpbmNsdWRlTWFya2VkPzogYm9vbGVhbjtcbiAgICAvKiogTGlzdGluZ3Mgbm9ybWFsbHkgY29tZSBPTkxZIGZyb20gdGhlIGF1dGhvcml0YXRpdmUgc291cmNlcyAodGhlIHNhbWUgbm9kZXMgd3JpdGVzIGdvIHRvIC0gcmVhZC15b3VyLXdyaXRlcykuIFdpdGggZmFsbGJhY2tzLCBhIGZhaWxpbmcgc2hhcmQncyByb3V0ZXMgYXJlIGNvdmVyZWQgYnkgdGhlIG5leHQgc291cmNlIGhvbGRpbmcgdGhlbSAoZS5nLiBhIHdpZGUgcmVhZCByZXBsaWNhKSBpbnN0ZWFkIG9mIHRoZSBjYWxsIGZhaWxpbmcgLSBoaWdoIGF2YWlsYWJpbGl0eSBhdCB0aGUgY29zdCBvZiBwb3NzaWJseSBtaXNzaW5nIGp1c3Qtd3JpdHRlbiBkYXRhLiBTaW5nbGUtc291cmNlIGFyY2hpdmVzIGlnbm9yZSB0aGUgZmxhZy4gKi9cbiAgICBmYWxsYmFja3M/OiBib29sZWFuO1xuICAgIC8qKiBTdG9yZS10by1zdG9yZSBsaXN0aW5nOiBvbmx5IGVudHJpZXMgd2hvc2UgYnl0ZXMgdGhlIG5vZGUgSVRTRUxGIGhvbGRzIC0gbmV2ZXIgZW50cmllcyBpdHMgaW5kZXggcmVkaXJlY3RzIHRvIGl0cyBvd24gb3RoZXIgc291cmNlcy4gQSBwZWVyIHJlYWRzIHdpdGggR2V0Q29uZmlnLmludGVybmFsICh3aGljaCBuZXZlciBjaGFzZXMgdGhvc2UgcmVkaXJlY3RzKSwgc28gbGlzdGluZyBhIHJlZGlyZWN0IHdvdWxkIGp1c3QgbWFrZSB0aGUgcGVlciBmbGFnIHRoZSBmaWxlIG1pc3NpbmcsIHB1cmdlIGl0LCByZS1saXN0IGl0LCBhbmQgbG9vcCBmb3JldmVyOyB0aGUgcGVlciBoZWFycyBhYm91dCBzdWNoIGZpbGVzIGZyb20gdGhlIHNvdXJjZSBhY3R1YWxseSBob2xkaW5nIHRoZW0gaW5zdGVhZC4gKi9cbiAgICBpbnRlcm5hbD86IGJvb2xlYW47XG59O1xuXG5leHBvcnQgdHlwZSBEZWxDb25maWcgPSB7XG4gICAgLyoqIFN0YW1wcyB0aGUgZGVsZXRpb24gKGl0cyB0b21ic3RvbmUpIHdpdGggdGhpcyB3cml0ZSB0aW1lIGluc3RlYWQgb2Ygbm93LiBTeW5jaHJvbml6YXRpb24gcGFzc2VzIHRoZSBPUklHSU5BTCBkZWxldGlvbiB0aW1lLCBzbyBkZWxldGlvbiBvcmRlcmluZyBzdXJ2aXZlcyBwcm9wYWdhdGlvbiBleGFjdGx5IGxpa2UgYW55IG90aGVyIHdyaXRlJ3Mgb3JkZXJpbmcuICovXG4gICAgbGFzdE1vZGlmaWVkPzogbnVtYmVyO1xuICAgIC8qKiBTZWUgU2V0Q29uZmlnLmludGVybmFsLiAqL1xuICAgIGludGVybmFsPzogYm9vbGVhbjtcbiAgICAvKiogU2VlIFNldENvbmZpZy5ub0NoZWNrcy4gKi9cbiAgICBub0NoZWNrcz86IGJvb2xlYW47XG4gICAgLyoqIFNlZSBTZXRDb25maWcuZmFsbGJhY2tzLiAqL1xuICAgIGZhbGxiYWNrcz86IGJvb2xlYW47XG4gICAgLyoqIFNlZSBHZXRDb25maWcucmV0cmllcy4gKi9cbiAgICByZXRyaWVzPzogbnVtYmVyO1xufTtcblxuZXhwb3J0IHR5cGUgR2V0SW5mb0NvbmZpZyA9IHtcbiAgICAvKiogQWxzbyByZXBvcnQgc2l6ZS0wIGVudHJpZXMgKHRvbWJzdG9uZXMgLSBhbiBlbXB0eSBmaWxlIElTIGEgbWlzc2luZyBmaWxlKS4gT2ZmIGJ5IGRlZmF1bHQsIHNvIGEgZGVsZXRlZCBrZXkgcmVwb3J0cyB1bmRlZmluZWQsIG1hdGNoaW5nIGdldC4gU3luY2hyb25pemF0aW9uLXN0eWxlIGNhbGxlcnMgcGFzcyB0aGlzIHdoZW4gdGhleSBuZWVkIGEgZGVsZXRpb24ncyB3cml0ZSB0aW1lIChlLmcuIHRvIGNvbXBhcmUgaXQgYWdhaW5zdCBhIHdyaXRlIHRoZXkgYXJlIGFib3V0IHRvIG1ha2UpLiAqL1xuICAgIGluY2x1ZGVUb21ic3RvbmVzPzogYm9vbGVhbjtcbiAgICAvKiogU2VlIEdldENvbmZpZy5ub0ZhbGxiYWNrczogYW5zd2VyIE9OTFkgZnJvbSB0aGUgcHJpbWFyeSBzb3VyY2UgKHRoZSBvbmUgd3JpdGVzIHdvdWxkIHRhcmdldCkgaW5zdGVhZCBvZiBmYWxsaW5nIGJhY2sgYWNyb3NzIHRoZSByZWR1bmRhbnQgc291cmNlcy4gKi9cbiAgICBub0ZhbGxiYWNrcz86IGJvb2xlYW47XG4gICAgLyoqIFNlZSBHZXRDb25maWcucmV0cmllcy4gKi9cbiAgICByZXRyaWVzPzogbnVtYmVyO1xuICAgIC8qKiBTZWUgR2V0Q29uZmlnLnNvdXJjZVVybDogYW5zd2VyIGZyb20gRVhBQ1RMWSB0aGlzIHNvdXJjZS4gKi9cbiAgICBzb3VyY2VVcmw/OiBzdHJpbmc7XG59O1xuXG5leHBvcnQgdHlwZSBDaGFuZ2VzQWZ0ZXJDb25maWcgPSB7XG4gICAgdGltZTogbnVtYmVyO1xuICAgIC8qKiBPbmx5IGtleXMgcm91dGluZyBpbnRvIG9uZSBvZiB0aGVzZSBbc3RhcnQsIGVuZCkgcmFuZ2VzLiBPbmx5IHNjYW5uaW5nIHBhc3NlcyB0aGlzIC0gaXQgbGV0cyBhIHN0b3JlIHN5bmNpbmcgYSBwYXJ0aWFsIHNoYXJkIGFzayBmb3IganVzdCBpdHMgc2xpY2UuICovXG4gICAgcm91dGVzPzogW251bWJlciwgbnVtYmVyXVtdO1xuICAgIC8qKiBTZWUgRmluZENvbmZpZy5pbnRlcm5hbCAtIHRoZSBjaGFuZ2UgZmVlZCBpcyBhIGxpc3RpbmcgdG9vLCBhbmQgcmVkaXJlY3QgZW50cmllcyBmYWlsIGEgcGVlcidzIGludGVybmFsIHJlYWRzIHRoZSBzYW1lIHdheS4gRGVsZXRpb25zIGFyZSBhbHdheXMgcmVwb3J0ZWQgKHRoZXkgYXJlIGluZGV4LW9ubHksIHRoZXJlIGFyZSBubyBieXRlcyB0byBob2xkKS4gKi9cbiAgICBpbnRlcm5hbD86IGJvb2xlYW47XG59O1xuXG5leHBvcnQgdHlwZSBTZXRDb25maWcgPSB7XG4gICAgLyoqIFRoZSB3cml0ZSB0aW1lIHRvIHN0YW1wIChzZWUgSUFyY2hpdmVzLnNldCkuIFJPVU5ERUQgdG8gd2hvbGUgbWlsbGlzZWNvbmRzIGJ5IGV2ZXJ5IGltcGxlbWVudGF0aW9uIC0gdGhlIGRpc2sgY2FuJ3Qgc3RvcmUgZnJhY3Rpb25hbCBtaWxsaXNlY29uZHMgYW55d2F5ICh1dGltZXMgcm91bmQtdHJpcHMgd2hvbGUgbXMpLCBzbyBhIGZyYWN0aW9uYWwgc3RhbXAgY291bGQgbmV2ZXIgYmUgcmVwcm9kdWNlZCBieSBwcm9wYWdhdGlvbiBhbmQgd291bGQgY29tcGFyZSBcIm5ld2VyXCIgdGhhbiBpdHMgb3duIGNvcGllcyBmb3JldmVyLiBSb3VuZGVkIHJhdGhlciB0aGFuIGZsb29yZWQgYmVjYXVzZSB1dGltZXMgZ29lcyB0aHJvdWdoIGEgc2Vjb25kcyBkb3VibGUgYW5kIGNhbiByZWFkIGJhY2sgYSBoYWlyIGJlbG93IHRoZSBzdGFtcGVkIG1pbGxpc2Vjb25kIChzZWUgQXJjaGl2ZXNEaXNrLmdldDIpLiAqL1xuICAgIGxhc3RNb2RpZmllZD86IG51bWJlcjtcbiAgICAvKiogTWFrZXMgdGhlIHdyaXRlIGFjY2VwdGFibGUgb24gaW1tdXRhYmxlIHRhcmdldHM6IGFuIGV4aXN0aW5nIHBhdGggaXMgc2ltcGx5IGtlcHQgKGltbXV0YWJpbGl0eSB3aW5zIC0gbm90aGluZyBpcyBvdmVyd3JpdHRlbikgaW5zdGVhZCBvZiB0aGUgd3JpdGUgdGhyb3dpbmcuIFJlcXVpcmVzIGxhc3RNb2RpZmllZC4gU3luY2hyb25pemF0aW9uIE1VU1QgcGFzcyB0aGlzIG9uIGV2ZXJ5IHB1c2ggLSBhIHBsYWluIHNldCB0aHJvd3Mgb24gaW1tdXRhYmxlIHRhcmdldHMsIHdoaWNoIHdvdWxkIGFib3J0IHJlY29uY2lsaWF0aW9uIHdoZW5ldmVyIG9uZSBzb3VyY2UgaW4gYSBjaGFpbiBpcyBpbW11dGFibGUuICovXG4gICAgZm9yY2VTZXRJbW11dGFibGU/OiBib29sZWFuO1xuICAgIC8qKiBTa2lwcyBSRURVTkRBTlQgdGFyZ2V0LXNpZGUgc2FmZXR5IHJlYWRzIGFyb3VuZCB0aGUgd3JpdGUgKGJhY2tibGF6ZTogdGhlIHBvc3QtdXBsb2FkIGV4aXN0ZW5jZSBwb2xsKS4gSXQgZG9lcyBOT1Qgc2tpcCBjaGVja3MgdGhhdCBhcmUgdGhlIHRhcmdldCdzIG9ubHkgb3JkZXJpbmcgZ3VhcmQ6IGJhY2tibGF6ZSdzIHByZS13cml0ZSBjb21wYXJpc29uIHN0YXlzLCBiZWNhdXNlIGIyIGhhcyBubyBzZXJ2ZXIgb2Ygb3VycyBlbmZvcmNpbmcgb25seS10YWtlLXRoZS1sYXRlc3QgLSB3aXRob3V0IGl0IGEgc3RhbGUgcHVzaCBsYW5kcyBvdmVyIGEgbmV3ZXIgdmFsdWUgb3IgdG9tYnN0b25lIGFuZCBiMidzIHNlbGYtc3RhbXBlZCB1cGxvYWQgdGltZSBsYXVuZGVycyBpdCBpbnRvIHRoZSBuZXdlc3QgY29weSBpbiB0aGUgc3lzdGVtIChnbG9iYWwgcmVzdXJyZWN0aW9uKS4gSG9zdGVkIHRhcmdldHMgcmUtY2hlY2sgc2VydmVyLXNpZGUsIHNvIHRoZWlyIGNsaWVudC1zaWRlIHNob3J0Y3V0cyBhcmUgc2FmZS4gKi9cbiAgICBub0NoZWNrcz86IGJvb2xlYW47XG4gICAgLyoqIFN0b3JlLXRvLXN0b3JlIHB1c2g6IHRoZSByZWNlaXZpbmcgbm9kZSB3cml0ZXMgcHVyZWx5IHRvIGl0cyBvd24gZGlzayBhbmQgaW5kZXgsIHdpdGggTk8gZG93bnN0cmVhbSBmYW4tb3V0ICh0aGUgcHVzaGluZyBzdG9yZSBvd25zIHByb3BhZ2F0aW9uIC0gZmFubmluZyBpdHMgcHVzaGVzIGJhY2sgb3V0IGlzIGhvdyB3cml0ZSBsb29wcyBiZXR3ZWVuIHN0b3JlcyBmb3JtKS4gV2luZG93IGFuZCByb3V0ZSBBUkUgc3RpbGwgY2hlY2tlZDogdGhlIHN0YW1wIG11c3QgZmFsbCBpbnNpZGUgb25lIG9mIHRoZSByZWNlaXZlcidzIGNvbmZpZ3VyZWQgd2luZG93cyBhbmQgcm91dGVzLCBzbyBhIGNvbmZ1c2VkIHBlZXIgY2Fubm90IHN0dWZmIGRhdGEgb250byBhIG5vZGUgdGhhdCB3YXMgbmV2ZXIgbWVhbnQgdG8gaG9sZCBpdC4gUmVxdWlyZXMgbGFzdE1vZGlmaWVkLiAqL1xuICAgIGludGVybmFsPzogYm9vbGVhbjtcbiAgICAvKiogV3JpdGVzIG5vcm1hbGx5IGdvIE9OTFkgdG8gdGhlIHdyaXRlIG5vZGUgKHRoZSBmaXJzdCBjdXJyZW50LXdpbmRvdyBzb3VyY2UgY292ZXJpbmcgdGhlIGtleSksIHJldHJ5aW5nIGl0IGV2ZW4gd2hpbGUgaXQgaXMgZG93biAtIGNvbnNpc3RlbnQsIGJ1dCB1bmF2YWlsYWJsZSB3aGVuIHRoYXQgbm9kZSBpcy4gV2l0aCBmYWxsYmFja3MsIHRoZSB3cml0ZSBub2RlIGlzIHN0aWxsIHRyaWVkIGZpcnN0LCBidXQgb24gZmFpbHVyZSB0aGUgd3JpdGUgbGFuZHMgb24gdGhlIG5leHQgY3VycmVudC13aW5kb3cgc291cmNlIGNvdmVyaW5nIHRoZSBrZXkgKHN5bmNocm9uaXphdGlvbiBtb3ZlcyBpdCB0byB0aGUgd3JpdGUgbm9kZSBsYXRlcikgLSBhdmFpbGFiaWxpdHkgYXQgdGhlIGNvc3Qgb2YgcmVhZHMgcG9zc2libHkgbWlzc2luZyB0aGUgd3JpdGUgdW50aWwgaXQgcHJvcGFnYXRlcy4gU2luZ2xlLXNvdXJjZSBhcmNoaXZlcyBpZ25vcmUgdGhlIGZsYWcuICovXG4gICAgZmFsbGJhY2tzPzogYm9vbGVhbjtcbiAgICAvKiogU2VlIEdldENvbmZpZy5yZXRyaWVzLiAqL1xuICAgIHJldHJpZXM/OiBudW1iZXI7XG4gICAgLyoqIFRoZSBzZXQgaXMgbm90IGEgd3JpdGUgYXQgYWxsOiBpdCBSRVNUT1JFUyBhIGZpbGUgbWFya2VkIGZvciBkZWxldGlvbiwgZmxpcHBpbmcgaXRzIGluZGV4IGVudHJ5IGJhY2sgdG8gbGl2ZSAod2l0aCBhIGZyZXNoIHdyaXRlIHRpbWUsIHNvIHRoZSByZXN0b3JlIG91dHJhbmtzIHRoZSBkZWxldGlvbiBldmVyeXdoZXJlIGl0IHByb3BhZ2F0ZWQpIC0gdGhlIGJ5dGVzIG5ldmVyIGxlZnQgdGhlIGRpc2ssIHNvIHJlYWRzIGp1c3Qgd29yayBhZ2Fpbi4gVGhlIGRhdGEgYnVmZmVyIGlzIGlnbm9yZWQgKGEgMS1ieXRlIHBsYWNlaG9sZGVyIHNhdGlzZmllcyB0aGUgZW1wdHktYnVmZmVyIHJ1bGUpOyB1c2UgSUFyY2hpdmVzLnVuZGVsZXRlIHJhdGhlciB0aGFuIHBhc3NpbmcgdGhpcyB5b3Vyc2VsZi4gVGhyb3dzIHdoZW4gdGhlIGtleSBoYXMgbm8gbWFya2VkIGRlbGV0aW9uIHRvIHJlc3RvcmUgKGl0cyBoaXN0b3J5IHdhcyBkcm9wcGVkLCBvciBpdCB3YXMgbmV2ZXIgZGVsZXRlZCkuICovXG4gICAgdW5kZWxldGU/OiBib29sZWFuO1xufTtcblxuLyoqIHNldExhcmdlRmlsZSdzIGNvbmZpZzogYSBTZXRDb25maWcgKGl0IElTIGEgc2V0IC0gdGhlIHNhbWUgaW1tdXRhYmlsaXR5LCBvcmRlcmluZywgaW50ZXJuYWwsIGFuZCBmYWxsYmFja3MgcnVsZXMgYXBwbHkpIHBsdXMgdGhlIHN0cmVhbSBjYXJyeWluZyB0aGUgYnl0ZXMuICovXG5leHBvcnQgdHlwZSBTZXRMYXJnZUZpbGVDb25maWcgPSBTZXRDb25maWcgJiB7XG4gICAgcGF0aDogc3RyaW5nO1xuICAgIGdldE5leHREYXRhKCk6IFByb21pc2U8QnVmZmVyIHwgdW5kZWZpbmVkPjtcbiAgICAvKiogUmV3aW5kcyB0aGUgc3RyZWFtIHRvIGl0cyBmaXJzdCBieXRlLiBXaXRob3V0IGl0IHRoZSB3cml0ZSBnZXRzIGV4YWN0bHkgT05FIGF0dGVtcHQ6IGEgcmV0cnkgKGEgZmFsbGJhY2sgc291cmNlLCBvciB0aGUgd3JpdGUgbm9kZSBjb21pbmcgYmFjaykgd291bGQgdXBsb2FkIHdoYXRldmVyIGlzIGxlZnQgb2YgYW4gYWxyZWFkeS1jb25zdW1lZCBzdHJlYW0gYXMgaWYgaXQgd2VyZSB0aGUgd2hvbGUgZmlsZS4gQ2FsbGVycyBob2xkaW5nIHRoZSBkYXRhIChhIGJ1ZmZlciwgb3IgYSBzb3VyY2UgdGhleSBjYW4gcmUtcmVhZCkgYWx3YXlzIHBhc3MgaXQgLSBhIGxhcmdlIHNldCB3aXRoIGZhbGxiYWNrcyBpcyBvbmx5IGFzIGF2YWlsYWJsZSBhcyB0aGlzLiAqL1xuICAgIHJlc3RhcnRTdHJlYW0/KCk6IFByb21pc2U8dm9pZD4gfCB2b2lkO1xufTtcblxuLy8gY3JlYXRlVGltZSBpcyBhIG1pc25vbWVyIGtlcHQgZm9yIGNvbXBhdGliaWxpdHkg4oCUIGl0IGlzIHJlYWxseSB0aGUgTEFTVC1XUklURSB0aW1lLCBzYW1lIGFzIGdldEluZm8ncyB3cml0ZVRpbWUuIE5laXRoZXIgQmFja2JsYXplIG5vciBvdXIgcmVtb3RlIHN0b3JhZ2UgdHJhY2tzIGEgZGlzdGluY3QgY3JlYXRpb24gZGF0ZTogZWFjaCB3cml0ZSBzdGFtcHMgYSBmcmVzaCB0aW1lc3RhbXAgb24gdGhlIGN1cnJlbnQgdmVyc2lvbiwgc28gYm90aCBmaWVsZHMgYXJlIGp1c3QgXCJ3aGVuIHRoZSBieXRlcyBzZXJ2ZWQgYnkgZ2V0KCkgd2VyZSBtb3N0IHJlY2VudGx5IHdyaXR0ZW5cIi4gQWx3YXlzIFdIT0xFIG1pbGxpc2Vjb25kczogd3JpdGUgdGltZXMgYXJlIHJvdW5kZWQgYXQgZXZlcnkgcHJvZHVjZXIgKHNlZSBTZXRDb25maWcubGFzdE1vZGlmaWVkKS5cbmV4cG9ydCB0eXBlIEFyY2hpdmVGaWxlSW5mbyA9IHsgcGF0aDogc3RyaW5nOyBjcmVhdGVUaW1lOiBudW1iZXI7IHNpemU6IG51bWJlciB9O1xuXG4vLyBBbiBpbi1wcm9ncmVzcyBiYWNrZ3JvdW5kIHN5bmNocm9uaXphdGlvbiB0YXNrIChzZWUgQXJjaGl2ZXNDb25maWcuc3luY2luZylcbmV4cG9ydCB0eXBlIFN5bmNBY3Rpdml0eSA9IHtcbiAgICAvLyBBIG1ldGFkYXRhIHNjYW4gaXMgYSBzaW5nbGUgbGlzdGluZyBjYWxsLCBzbyBpdCBoYXMgbm8gaW5jcmVtZW50YWwgcHJvZ3Jlc3MgLSBqdXN0IHRoYXQgaXQncyBydW5uaW5nIGFuZCBzaW5jZSB3aGVuLiBBIGZ1bGwgc3luYyBrbm93cyBpdHMgZXhhY3QgZmlsZS9ieXRlIHByb2dyZXNzLlxuICAgIHR5cGU6IFwibWV0YWRhdGFTY2FuXCIgfCBcImZ1bGxTeW5jXCI7XG4gICAgc291cmNlRGVidWdOYW1lOiBzdHJpbmc7XG4gICAgc3RhcnRUaW1lOiBudW1iZXI7XG4gICAgZG9uZUZpbGVzPzogbnVtYmVyO1xuICAgIHRvdGFsRmlsZXM/OiBudW1iZXI7XG4gICAgZG9uZUJ5dGVzPzogbnVtYmVyO1xuICAgIHRvdGFsQnl0ZXM/OiBudW1iZXI7XG59O1xuXG5leHBvcnQgdHlwZSBBcmNoaXZlc0NvbmZpZyA9IHtcbiAgICAvLyBXaGV0aGVyIGdldENoYW5nZXNBZnRlcjIgaXMgbmF0aXZlbHkgaW5kZXgtYmFja2VkIChmYXN0IGNoYW5nZSBwb2xsaW5nOyBldmVyeSBiYWNrZW5kIHN0aWxsIHNlcnZlcyBpdCwgYnV0IHRoZSBvdGhlcnMgZW11bGF0ZSBpdCB3aXRoIGEgZnVsbCBsaXN0aW5nKVxuICAgIHN1cHBvcnRzQ2hhbmdlc0FmdGVyPzogYm9vbGVhbjtcbiAgICAvLyBUaGUgYnVja2V0J3MgZnVsbCByb3V0aW5nIGNvbmZpZyAoUk9VVElOR19GSUxFKS4gQWJzZW50IGZvciBzb3VyY2VzIHRoYXQgZG9uJ3QgaGF2ZSBvbmUgKGEgYmFyZSBkaXNrIHNvdXJjZSwgb3IgYSBidWNrZXQgdGhhdCBkb2Vzbid0IGV4aXN0IHlldCkuXG4gICAgcmVtb3RlQ29uZmlnPzogUmVtb3RlQ29uZmlnO1xuICAgIC8vIExpdmUgaW5kZXggdG90YWxzICh0b21ic3RvbmVzIGV4Y2x1ZGVkKSwga2VwdCB1cCB0byBkYXRlIGluIG1lbW9yeSBvbiBldmVyeSBtdXRhdGlvbiBhbmQgcmVjb21wdXRlZCBvbiBsb2FkIC0gc28gYW55IGRyaWZ0IGhlYWxzIG9uIHJlc3RhcnRcbiAgICBpbmRleD86IHsgZmlsZUNvdW50OiBudW1iZXI7IGJ5dGVDb3VudDogbnVtYmVyIH07XG4gICAgLyoqIEZpbGVzIE1BUktFRCBmb3IgZGVsZXRpb24gKGRlbGV0ZWQsIGJ5dGVzIHN0aWxsIGtlcHQgYXMgaGlzdG9yeSAtIHNlZSBTZXRDb25maWcudW5kZWxldGUpOiBob3cgbWFueSwgaG93IGJpZywgYW5kIHRoZSBkZWxldGUgdGltZSBvZiB0aGUgb2xkZXN0IG9uZSAtIHdoaWNoIGlzIGhvdyBmYXIgYmFjayB0aGUgZGVsZXRpb24gaGlzdG9yeSByZWFjaGVzLiAqL1xuICAgIG1hcmtlZEluZGV4PzogeyBmaWxlQ291bnQ6IG51bWJlcjsgYnl0ZUNvdW50OiBudW1iZXI7IG9sZGVzdERlbGV0ZVRpbWU/OiBudW1iZXIgfTtcbiAgICAvLyBUaGUgc2FtZSB0b3RhbHMgYnJva2VuIGRvd24gYnkgd2hpY2ggc291cmNlIGN1cnJlbnRseSBob2xkcyBlYWNoIGZpbGUncyBieXRlcyAodGhlIGZpcnN0IGVudHJ5IGlzIHRoZSBzZXJ2ZXIncyBvd24gZGlzaylcbiAgICBpbmRleFNvdXJjZXM/OiB7IGRlYnVnTmFtZTogc3RyaW5nOyBmaWxlQ291bnQ6IG51bWJlcjsgYnl0ZUNvdW50OiBudW1iZXIgfVtdO1xuICAgIC8vIFRoZSBzZXJ2ZXIncyBjb25maWd1cmVkIHJlYWRlckRpc2tMaW1pdCwgd2hlbiBpdCBydW5zIGFzIGEgYm91bmRlZCByZWFkIGNhY2hlXG4gICAgcmVhZGVyRGlza0xpbWl0PzogbnVtYmVyO1xuICAgIC8vIEJhY2tncm91bmQgc3luY2hyb25pemF0aW9uIGN1cnJlbnRseSBpbiBwcm9ncmVzcyAoZW1wdHkgd2hlbiBpZGxlKVxuICAgIHN5bmNpbmc/OiBTeW5jQWN0aXZpdHlbXTtcbn07XG5cbi8vIEEgc3luY2hyb25pemF0aW9uIHNvdXJjZSBvZiBhIEJsb2JTdG9yZSAod2hpY2ggc3luY2hyb25pemVzIGFuIGluZGV4ICsgbG9jYWwgY2FjaGUgZnJvbSB0aGVtKVxuZXhwb3J0IHR5cGUgQXJjaGl2ZXNTb3VyY2UgPSB7XG4gICAgc291cmNlOiBJQXJjaGl2ZXM7XG4gICAgLyoqIFRoZSBwZXJzaXN0ZW50IGlkZW50aXR5IG9mIHRoZSBlbmRwb2ludDogaXRzIHJvdXRpbmcgVVJMIChob3N0ZWQvYmFja2JsYXplKSwgb3IgdGhlIGRpc2sgZm9sZGVyIHBhdGggZm9yIHRoZSBiYXNlIGRpc2sgc291cmNlLiBUaGUgc3RvcmUgcGVyc2lzdHMgdGhpcyAodmlhIGl0cyBhcHBlbmQtb25seSBzb3VyY2VzIGxpc3QpIGFzIEluZGV4RW50cnkuc291cmNlc0xpc3RJbmRleCwgc28gaXQgbXVzdCBtZWFuIHRoZSBzYW1lIGVuZHBvaW50IGZvcmV2ZXIuICovXG4gICAgdXJsOiBzdHJpbmc7XG4gICAgLy8gRnJvbSB0aGUgc291cmNlJ3MgQ29tbW9uQ29uZmlnLCBidXQgQUxMIG9mIHRoZW06IHRoZSBzYW1lIGVuZHBvaW50IChzYW1lIHVybCtyb3V0ZSwgaWdub3JpbmcgdGhlIHdpbmRvdykgY2FuIGFwcGVhciBpbiB0aGUgcm91dGluZyBjb25maWcgdW5kZXIgc2V2ZXJhbCB3aW5kb3dzIGF0IG9uY2UgLSBtb3N0IGNvbW1vbmx5IHdoZW4gYSBkZXBsb3kgc3dpdGNob3ZlciBoYXMgc3BsaXQgb25lIHdpbmRvdyBpbiB0d28gYXJvdW5kIGFuIGludGVybWVkaWF0ZS4gSXQgaXMgT05FIHNvdXJjZSB0aGF0IGtub3dzIGFsbCBpdHMgd2luZG93cywgbmV2ZXIgc2V2ZXJhbCBzb3VyY2VzLiBUaGUgd2luZG93IHJvdXRlcyBXUklURVM6IHRoZSBzb3VyY2UgcmVjZWl2ZXMgd3JpdGVzIHdoaWxlIEFOWSBvZiBpdHMgd2luZG93cyBpcyBzdGlsbCBvcGVuIChzZWUgd2luZG93c0FjY2VwdFdyaXRlcykuIFdpbmRvd3MgZG8gTk9UIGZpbHRlciBzY2FubmluZzogYSBzY2FuIGlzIHVzIGFza2luZyB0aGUgc291cmNlIHdoYXQgaXQgYWxyZWFkeSBob2xkcywgYW5kIGV4aXN0aW5nIHZhbHVlcyBzeW5jaHJvbml6ZSByZWdhcmRsZXNzIG9mIHRoZWlyIHdyaXRlIHRpbWVzICh0aGUgc2FtZSByZWFzb25pbmcgdGhhdCBsZXRzIHN5bmNocm9uaXphdGlvbiBpZ25vcmUgdGhlIGltbXV0YWJsZSBmbGFnKS5cbiAgICB2YWxpZFdpbmRvd3M6IFtudW1iZXIsIG51bWJlcl1bXTtcbiAgICAvLyBGcm9tIHRoZSBzb3VyY2UncyBDb21tb25Db25maWcgKGludGVyc2VjdGVkIHdpdGggdGhlIG93bmluZyBzdG9yZSdzIG93biByb3V0ZSk6IG9ubHkga2V5cyByb3V0aW5nIGludG8gW3N0YXJ0LCBlbmQpIGFyZSBhY2NlcHRlZCBmcm9tIHRoaXMgc291cmNlJ3Mgc2NhbnMgYW5kIHNlbnQgdG8gaXQgaW4gd3JpdGVzL3JlY29uY2lsaWF0aW9uLiBUaGUgcm91dGluZyBmaWxlIGlzIGV4ZW1wdCAtIGNvbmZpZyBmbG93cyBldmVyeXdoZXJlLiBBYnNlbnQgPSBhbGwga2V5cy5cbiAgICByb3V0ZT86IFtudW1iZXIsIG51bWJlcl07XG4gICAgLy8gRnJvbSB0aGUgc291cmNlJ3MgQ29tbW9uQ29uZmlnOyBzZWUgdGhlcmUuXG4gICAgbm9GdWxsU3luYz86IGJvb2xlYW47XG4gICAgLy8gRnJvbSB0aGUgc291cmNlJ3MgQ29tbW9uQ29uZmlnOiBhIGRlcGxveSBzd2l0Y2hvdmVyJ3MgdGVtcG9yYXJ5IGFsdGVybmF0ZS1wb3J0IGVudHJ5ICh0aGUgdmFsdWUgaXMgdGhlIHVybCBvZiB0aGUgc291cmNlIGl0IHdhcyBzcGxpdCBvdXQgb2YpLiBPbmNlIGl0cyB3aW5kb3cgaXMgcGFzdCwgdGhlIHBvcnQgaXQgcG9pbnRzIGF0IGlzIGdvbmUgZm9yIGdvb2QgLSBzbyBpdCBpcyBuZXZlciBzY2FubmVkIHRoZW4sIGFuZCBzY2FuIGZhaWx1cmVzIGFyZSBuZXZlciByZXRyaWVkLlxuICAgIGludGVybWVkaWF0ZT86IHN0cmluZztcbiAgICAvLyBUaGUgcm91dGluZy1jb25maWcgZW50cnkgdGhpcyBzb3VyY2Ugd2FzIGJ1aWx0IGZyb20gKGFic2VudCBmb3IgdGhlIGJhc2UgZGlzayBzb3VyY2UpLiBJdHMgYHR5cGVgIGRlY2lkZXMgZmFzdC13cml0ZSBmbHVzaCB0aW1pbmc6IHR5cGUtXCJyZW1vdGVcIiBkb3duc3RyZWFtIHNvdXJjZXMgKG91ciBvd24gc3RvcmFnZSBzZXJ2ZXJzKSBmbHVzaCBxdWlja2x5IChjaGVhcCwgYW5kIHdlIHdhbnQgY3Jvc3Mtbm9kZSByZWR1bmRhbmN5IGZhc3QpLCB3aGlsZSBvdGhlcnMgKGUuZy4gYmFja2JsYXplKSBrZWVwIHRoZSBmdWxsIHdyaXRlRGVsYXkgc28gZXhwZW5zaXZlIGV4dGVybmFsIHdyaXRlcyBzdGF5IGNvYWxlc2NlZC4gVGhlIHdpbmRvdy9yb3V0ZSBPTiB0aGlzIGNvbmZpZyBhcmUgdGhlIFNPVVJDRSdzIG93bjsgQXJjaGl2ZXNTb3VyY2UudmFsaWRXaW5kb3cvcm91dGUgYXJlIHdoYXQgdGhlIG93bmluZyBzdG9yZSBhY3R1YWxseSB1c2VzIChyb3V0ZSBpcyBpbnRlcnNlY3RlZCB3aXRoIHRoZSBzdG9yZSdzIHJvdXRlKS5cbiAgICBzb3VyY2VDb25maWc/OiBTb3VyY2VDb25maWc7XG4gICAgLy8gU3RhYmxlIGlkZW50aXR5IG9mIHRoZSB1bmRlcmx5aW5nIGVuZHBvaW50IChpdHMgY29uZmlnIHdpdGggd2luZG93cy9yb3V0ZXMgc3RyaXBwZWQpIC0gaG93IEJsb2JTdG9yZS51cGRhdGVTb3VyY2VzIHJlY29nbml6ZXMgYSBzb3VyY2UgYWNyb3NzIGNvbmZpZyBjaGFuZ2VzIHNvIGl0IGNhbiB1cGRhdGUgaXQgaW4gcGxhY2UgaW5zdGVhZCBvZiByZW1vdmluZyBhbmQgcmUtYWRkaW5nIGl0XG4gICAgaWRlbnRpdHk/OiBzdHJpbmc7XG59O1xuXG4vLyBFcnJvciBtYXJrZXIgYSBzZXJ2ZXIgaW5jbHVkZXMgd2hlbiBhIGZyZXNobHktc3RhbXBlZCB3cml0ZSByZWFjaGVzIGl0IG91dHNpZGUgaXRzIHZhbGlkIHdpbmRvd3MgKHRoZSBjbGllbnQgcmVzb2x2ZWQgaXRzIHRhcmdldCwgdGhlbiB0aW1lIGNyb3NzZWQgYSB3aW5kb3cgYm91bmRhcnkgYmVmb3JlIHRoZSB3cml0ZSBsYW5kZWQpLiBDbGllbnRzIGRldGVjdCB0aGlzIG1hcmtlciBhbmQgcmUtcmVzb2x2ZSB0aGUgY3VycmVudGx5LXZhbGlkIHNvdXJjZSwgcmV0cnlpbmcgT05DRSAtIGJvdW5kYXJpZXMgYXJlIGZhciBhcGFydCwgc28gaGl0dGluZyBpdCB0d2ljZSBpbiBvbmUgYXR0ZW1wdCBtZWFucyBzb21ldGhpbmcgaXMgYWN0dWFsbHkgd3JvbmcuXG5leHBvcnQgY29uc3QgU1RPUkFHRV9XUk9OR19WQUxJRF9XSU5ET1cgPSBcIlJFTU9URV9TVE9SQUdFX1dST05HX1ZBTElEX1dJTkRPV19hN2MxZjA0ZVwiO1xuXG4vLyBFcnJvciBtYXJrZXIgYSBzZXJ2ZXIgaW5jbHVkZXMgd2hlbiBhIGZyZXNobHktc3RhbXBlZCB3cml0ZSdzIGtleSByb3V0ZXMgb3V0c2lkZSB0aGUgc2hhcmRzIHRoaXMgc2VydmVyIGhhbmRsZXMgKHRoZSBjbGllbnQncyBjb25maWcgZGlzYWdyZWVzIHdpdGggdGhlIHNlcnZlcidzIC0gY2xpZW50cyByZS1yZXNvbHZlIG9uY2UpXG5leHBvcnQgY29uc3QgU1RPUkFHRV9XUk9OR19ST1VURSA9IFwiUkVNT1RFX1NUT1JBR0VfV1JPTkdfUk9VVEVfYzk0ZDJlMTdcIjtcblxuLy8gRXJyb3IgbWFya2VyIGEgc2VydmVyIGluY2x1ZGVzIHdoZW4gYSB3cml0ZSByZWFjaGVzIGEgc3RvcmUgd2hvc2Ugb3duIHJvdXRpbmcgY29uZmlnIGhhcyBOTyBlbnRyeSBmb3IgaXQgb24gdGhhdCBzZXJ2ZXIgKG9yIHRoYXQgaGFzIG5vIHJvdXRpbmcgY29uZmlnIGF0IGFsbCkgLSBhY2NlcHRpbmcgdGhlIHdyaXRlIHdvdWxkIHN0b3JlIGRhdGEgbm90aGluZyBzY2FucyBvciByZWNvbmNpbGVzLiBDbGllbnRzIHJlLXJlc29sdmUgb25jZSwgZXhhY3RseSBsaWtlIHRoZSBtYXJrZXJzIGFib3ZlOiB0aGUgdXN1YWwgY2F1c2UgaXMgdGhlIGNsaWVudCBydW5uaW5nIGEgZGlmZmVyZW50IGNvbmZpZyB0aGFuIHRoZSBzdG9yZS5cbmV4cG9ydCBjb25zdCBTVE9SQUdFX05PVF9DT05GSUdVUkVEID0gXCJSRU1PVEVfU1RPUkFHRV9OT1RfQ09ORklHVVJFRF9lNTFiN2Q5MlwiO1xuXG5leHBvcnQgY29uc3QgRlVMTF9ST1VURTogW251bWJlciwgbnVtYmVyXSA9IFswLCAxXTtcblxuLy8gQSBrZXkgY29udGFpbmluZyB0aGlzIHNlbnRpbmVsIGRvZXNuJ3QgaGF2ZSBhIGZpeGVkIHNoYXJkOiBzZXRWYXJpYWJsZVNoYXJkIHBpY2tzIHRoZSAobG93ZXN0IGxhdGVuY3ksIHVwKSB3cml0ZSBzaGFyZCwgYXBwZW5kcyBcIl88dmFsdWUgaW4gdGhlIHNoYXJkJ3Mgcm91dGU+XCIgZGlyZWN0bHkgYWZ0ZXIgdGhlIHNlbnRpbmVsLCBhbmQgcmV0dXJucyB0aGUgbWF0ZXJpYWxpemVkIGtleS4gZ2V0Um91dGUgdHJlYXRzIHRoYXQgc3VmZml4IGFzIGEgY29tcGxldGUgcm91dGUgb3ZlcnJpZGUuXG5leHBvcnQgY29uc3QgVkFSSUFCTEVfU0hBUkQgPSBcIlZBUklBQkxFX1NIQVJEX2YwMjM0amZhaDA4Zmd5aGZneXNzZGRzODNubXBcIjtcbi8vIE5vIGdyYWNlIHBhc3QgdGhlIGVuZDogYSB3aW5kb3cgYm91bmRhcnkgaXMgYSBoYXJkIGhhbmRvZmYgKGNsaWVudHMgcmV0cnkgYSByZWplY3RlZCB3cml0ZSBhZ2FpbnN0IHRoZSBuZXdseS12YWxpZCBzb3VyY2UsIHNvIGxlbmllbmN5IGhlcmUgd291bGQgb25seSBkZXN5bmNocm9uaXplIHRoZSBoYW5kb2ZmKVxuLy8gIC0gV3JpdGluZyB0byBvbGRlciB2YWxpZCBzdGF0ZSB3aW5kb3dzIGlzIGZpbmUsIHRob3VnaC4gV2UgbmVlZCB0aGlzIHRvIGluZ2VzdCB0aGUgb2xkIGRhdGEgd2hlbiB3ZSdyZSBzeW5jaHJvbml6aW5nIG5vZGVzIHRvIGdldCB0aGVtIHVwIHRvIGRhdGUgYW55d2F5LiBcbmV4cG9ydCBmdW5jdGlvbiB3aW5kb3dBY2NlcHRzV3JpdGVzKHZhbGlkV2luZG93OiBbbnVtYmVyLCBudW1iZXJdIHwgdW5kZWZpbmVkKTogYm9vbGVhbiB7XG4gICAgaWYgKCF2YWxpZFdpbmRvdykgcmV0dXJuIHRydWU7XG4gICAgcmV0dXJuIHZhbGlkV2luZG93WzFdID4gRGF0ZS5ub3coKTtcbn1cbi8vIEEgc291cmNlICh3aGljaCBjYW4gaG9sZCBzZXZlcmFsIHdpbmRvd3MpIGFjY2VwdHMgd3JpdGVzIHdoaWxlIEFOWSBvZiBpdHMgd2luZG93cyBpcyBzdGlsbCBvcGVuLiBObyB3aW5kb3dzID0gdGhlIGJhc2UgZGlzayBvZiBhbiBpbmVydCBzdG9yZSAobm90IGluIHRoZSBjb25maWcpLCB3aGljaCBuZXZlciByZWNlaXZlcyBmYW4tb3V0IHdyaXRlcyBhbnl3YXkuXG5leHBvcnQgZnVuY3Rpb24gd2luZG93c0FjY2VwdFdyaXRlcyh2YWxpZFdpbmRvd3M6IFtudW1iZXIsIG51bWJlcl1bXSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB2YWxpZFdpbmRvd3Muc29tZSh3aW5kb3dBY2NlcHRzV3JpdGVzKTtcbn1cblxuLy8gQWJvdmUgdGhpcywgc2V0IHRyYW5zcGFyZW50bHkgc3RyZWFtcyB0aHJvdWdoIHNldExhcmdlRmlsZTogb25lIGdpYW50IHdpcmUgbWVzc2FnZSB3b3VsZCBleGNlZWQgdGhlIHRyYW5zcG9ydCBsaW1pdCBhbmQgbGFnIGV2ZXJ5IG90aGVyIGNsaWVudCBzaGFyaW5nIHRoZSBjb25uZWN0aW9uXG5leHBvcnQgY29uc3QgTEFSR0VfU0VUX1RIUkVTSE9MRCA9IDggKiAxMDI0ICogMTAyNDtcblxuLyoqIFRoZSBzZXRMYXJnZUZpbGUgc3RyZWFtIG92ZXIgYW4gaW4tbWVtb3J5IGJ1ZmZlciwgaW4gTEFSR0VfU0VUX1RIUkVTSE9MRCBzbGljZXMgLSBob3cgc2V0IHRyYW5zcGFyZW50bHkgYmVjb21lcyBzZXRMYXJnZUZpbGUgZm9yIGxhcmdlIGJ1ZmZlcnMuIFNwcmVhZCBpbnRvIHRoZSBjb25maWc6IGl0IHByb3ZpZGVzIGJvdGggZ2V0TmV4dERhdGEgYW5kIHJlc3RhcnRTdHJlYW0gKHRoZSBidWZmZXIgaXMgc3RpbGwgaGVsZCwgc28gYSByZXRyeSBjb3N0cyBub3RoaW5nKS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBidWZmZXJDaHVua1N0cmVhbShkYXRhOiBCdWZmZXIpOiB7IGdldE5leHREYXRhKCk6IFByb21pc2U8QnVmZmVyIHwgdW5kZWZpbmVkPjsgcmVzdGFydFN0cmVhbSgpOiB2b2lkIH0ge1xuICAgIGxldCBvZmZzZXQgPSAwO1xuICAgIHJldHVybiB7XG4gICAgICAgIGdldE5leHREYXRhOiBhc3luYyAoKSA9PiB7XG4gICAgICAgICAgICBpZiAob2Zmc2V0ID49IGRhdGEubGVuZ3RoKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgbGV0IGNodW5rID0gZGF0YS5zdWJhcnJheShvZmZzZXQsIG9mZnNldCArIExBUkdFX1NFVF9USFJFU0hPTEQpO1xuICAgICAgICAgICAgb2Zmc2V0ICs9IGNodW5rLmxlbmd0aDtcbiAgICAgICAgICAgIHJldHVybiBjaHVuaztcbiAgICAgICAgfSxcbiAgICAgICAgcmVzdGFydFN0cmVhbTogKCkgPT4ge1xuICAgICAgICAgICAgb2Zmc2V0ID0gMDtcbiAgICAgICAgfSxcbiAgICB9O1xufVxuXG4vLyBSZS1leHBvcnRlZCBmb3IgdGhlIGV4aXN0aW5nIGltcG9ydGVycyAtIHRoZSBpbXBsZW1lbnRhdGlvbnMgKGFuZCBtb3ZlQXJjaGl2ZUZpbGUpIGxpdmUgaW4gYXJjaGl2ZUhlbHBlcnMudHMsIGJlc2lkZSB0aGlzIGludGVyZmFjZSByYXRoZXIgdGhhbiBpbiBpdFxuZXhwb3J0IHsgY29weUFyY2hpdmVGaWxlIH0gZnJvbSBcIi4vYXJjaGl2ZUhlbHBlcnNcIjtcblxuLyoqIG1vdmUncyBjb25maWcuIFRoZXJlIGlzIGRlbGliZXJhdGVseSBubyBsYXN0TW9kaWZpZWQ6IHRoZSBkZXN0aW5hdGlvbiBpcyBBTFdBWVMgc3RhbXBlZCBmcmVzaCAoc2VlIElBcmNoaXZlcy5tb3ZlKSAtIGEgbW92ZSBpcyBhIG5ldyB3cml0ZSBhdCB0aGUgbmV3IHBhdGgsIGFuZCBhIHByZXNlcnZlZCBvbGQgc3RhbXAgaXMgaG93IGEgbW92ZWQgZmlsZSBsb3NlcyB0byBhIHN0YWxlIHRvbWJzdG9uZSB0aGVyZSBhbmQgdmFuaXNoZXMuICovXG5leHBvcnQgdHlwZSBNb3ZlRmlsZUNvbmZpZyA9IHtcbiAgICBmcm9tUGF0aDogc3RyaW5nO1xuICAgIHRvUGF0aDogc3RyaW5nO1xufTtcblxuZXhwb3J0IHR5cGUgQXJjaGl2ZXNTeW5jU291cmNlU3RhdHVzID0ge1xuICAgIGRlYnVnTmFtZTogc3RyaW5nO1xuICAgIHZhbGlkV2luZG93czogW251bWJlciwgbnVtYmVyXVtdO1xuICAgIHJvdXRlPzogW251bWJlciwgbnVtYmVyXTtcbiAgICBub0Z1bGxTeW5jPzogYm9vbGVhbjtcbiAgICBzdXBwb3J0c0NoYW5nZXNBZnRlcjogYm9vbGVhbjtcbiAgICBpbml0aWFsU2NhbkNvbXBsZXRlOiBib29sZWFuO1xuICAgIC8vIEZpbGVzIHNlZW4gaW4gdGhpcyBzb3VyY2UncyBzY2FucyAvIGNoYW5nZSBwb2xscyBzbyBmYXJcbiAgICBzY2FubmVkQ291bnQ6IG51bWJlcjtcbn07XG5leHBvcnQgdHlwZSBBcmNoaXZlc1N5bmNTdGF0dXMgPSB7XG4gICAgYWxsU2NhbnNDb21wbGV0ZTogYm9vbGVhbjtcbiAgICAvLyBOdW1iZXIgb2YgZmlsZXMgaW4gdGhlIGluZGV4XG4gICAgaW5kZXhTaXplOiBudW1iZXI7XG4gICAgc291cmNlczogQXJjaGl2ZXNTeW5jU291cmNlU3RhdHVzW107XG59O1xuXG4vLyBOT1RFOiBXZSBkb24ndCBwcmVzZW50bHkgaGF2ZSBhbiBhcHBlbmQgZnVuY3Rpb24gaGVyZSBiZWNhdXNlIGEgc3VycHJpc2luZyBudW1iZXIgb2Ygc3RvcmFnZSBzeXN0ZW1zIGRvbid0IHN1cHBvcnQgaXQgKGJhY2tibGF6ZSwgZmlsZSBzeXN0ZW0gYXBpKS4gSXQgd291bGQgYWxzbyBjb21wbGljYXRlIHRoaW5ncyBhcyBub3cgdGhlcmUgbmVlZHMgdG8gYmUgcmVhbGx5IGEgc2luZ2xlIHNvdXJjZSBvZiB0cnV0aCBvZiBhIGZpbGUsIGFuZCBpZiB5b3UgYXBwZW5kIHRvIHRoZSB3cm9uZyBzaW5nbGUgc291cmNlIG9mIHRydXRoLCB0aGluZ3MganVzdCBiZWNvbWUgdmVyeSBjb21wbGljYXRlZC4gXG5leHBvcnQgaW50ZXJmYWNlIElBcmNoaXZlcyB7XG4gICAgZ2V0RGVidWdOYW1lKCk6IHN0cmluZztcbiAgICAvKiogV2hldGhlciB3cml0ZXMgd291bGQgYmUgYWNjZXB0ZWQgKGNyZWRlbnRpYWxzIGV4aXN0LCB0aGUgYWNjb3VudCB0cnVzdHMgdGhpcyBtYWNoaW5lLCBldGMpLiBDaGVja2VkIHdpdGhvdXQgd3JpdGluZyBhbnl0aGluZy4gKi9cbiAgICBoYXNXcml0ZUFjY2VzcygpOiBQcm9taXNlPGJvb2xlYW4+O1xuICAgIC8qKlxuICAgICAqIFJlYWRzIGF1dG9tYXRpY2FsbHkgZmFsbCBiYWNrIGFjcm9zcyB0aGUgcmVkdW5kYW50IHNvdXJjZXMgdW5sZXNzIGNvbmZpZy5ub0ZhbGxiYWNrcyBpcyBzZXQuXG4gICAgICogQSBmYWxsYmFjayBjb3B5IGNhbiBsYWcgdGhlIHdyaXRlIHRhcmdldCwgc28gYSBjYWxsZXIgcmVhZGluZyBzdGF0ZSBpbiBvcmRlciB0byBtdXRhdGUgaXRcbiAgICAgKiAoZS5nLiB4KyspLCB3aGVyZSBhY3Rpbmcgb24gcHJldmlvdXMgc3RhdGUgd291bGQgY2F1c2UgYmlnIGlzc3Vlcywgc2hvdWxkIHBhc3Mgbm9GYWxsYmFja3MgLVxuICAgICAqIGFuZCB0cnkvY2F0Y2ggdGhlIHJlYWQsIGhhbmRsaW5nIHRoZSBjYXRjaCBjYXNlIChhIGRvd24gcHJpbWFyeSBpcyByZXRyaWVkIGZvciBhIHdoaWxlLCB0aGVuXG4gICAgICogdGhyb3dzIGluc3RlYWQgb2YgZGVncmFkaW5nIHRvIGEgc3RhbGUgY29weSkuXG4gICAgICovXG4gICAgZ2V0KGZpbGVOYW1lOiBzdHJpbmcsIGNvbmZpZz86IEdldENvbmZpZyk6IFByb21pc2U8QnVmZmVyIHwgdW5kZWZpbmVkPjtcbiAgICAvKiogU2VlIGdldCBmb3IgdGhlIGZhbGxiYWNrIHNlbWFudGljcyAoYW5kIHdoZW4gdG8gcGFzcyBub0ZhbGxiYWNrcykuIHVybCBpcyB0aGUgY29uZmlnIFVSTCBvZiB0aGUgc291cmNlIHRoYXQgYW5zd2VyZWQgLSB0aGUgYXV0aG9yaXR5IHRoZSBkYXRhIChvciB0aGUgXCJkb2VzIG5vdCBleGlzdFwiKSBjYW1lIGZyb20uIE11bHRpLXNvdXJjZSBpbXBsZW1lbnRhdGlvbnMgKEFyY2hpdmVzQ2hhaW4pIEFMV0FZUyByZXR1cm4gYW4gb2JqZWN0OiB3aGVuIHRoZSB2YWx1ZSBkb2Vzbid0IGV4aXN0IHRoZXJlIGlzIHN0aWxsIGEgc2VydmVyIHNheWluZyBpdCBkb2Vzbid0IGV4aXN0LCBzbyB0aGV5IHJldHVybiB7IHVybCB9IGFsb25lIHJhdGhlciB0aGFuIHVuZGVmaW5lZC4gU2luZ2xlLXNvdXJjZSBiYWNrZW5kcyByZXR1cm4gdW5kZWZpbmVkIGZvciBhYnNlbnQgKHRoZXkgQVJFIHRoZSBhdXRob3JpdHkpLiAqL1xuICAgIGdldDIoZmlsZU5hbWU6IHN0cmluZywgY29uZmlnPzogR2V0Q29uZmlnKTogUHJvbWlzZTx7IGRhdGE6IEJ1ZmZlcjsgd3JpdGVUaW1lOiBudW1iZXI7IHNpemU6IG51bWJlcjsgdXJsPzogc3RyaW5nIH0gfCB7IGRhdGE/OiB1bmRlZmluZWQ7IHdyaXRlVGltZT86IHVuZGVmaW5lZDsgc2l6ZT86IHVuZGVmaW5lZDsgdXJsOiBzdHJpbmcgfSB8IHVuZGVmaW5lZD47XG4gICAgLyoqXG4gICAgICogbGFzdE1vZGlmaWVkIHN0YW1wcyB0aGUgd3JpdGUgd2l0aCB0aGF0IGxhc3Qtd3JpdGUgdGltZSBpbnN0ZWFkIG9mIG5vdy4gSWYgaXQgaXMgT0xERVIgdGhhblxuICAgICAqIHRoZSBmaWxlJ3MgY3VycmVudCBsYXN0LXdyaXRlIHRpbWUgdGhlIHdyaXRlIG5vLW9wcyAoc28gZGVsYXllZCAvIHN5bmNocm9uaXplZCB3cml0ZXMgY2FuXG4gICAgICogbmV2ZXIgY2xvYmJlciBuZXdlciBkYXRhKS4gVGltZXMgbW9yZSB0aGFuIDE1IG1pbnV0ZXMgaW4gdGhlIGZ1dHVyZSBhcmUgcmVqZWN0ZWQuXG4gICAgICpcbiAgICAgKiBSZXR1cm5zIHRoZSBmdWxsIGtleSBhY3R1YWxseSB3cml0dGVuIC0gaWRlbnRpY2FsIHRvIGZpbGVOYW1lLCBFWENFUFQgZm9yIGtleXMgY29udGFpbmluZ1xuICAgICAqIFZBUklBQkxFX1NIQVJELCB3aGVyZSB0aGUgc2hhcmQgdmFsdWUgaXMgbWF0ZXJpYWxpemVkIGludG8gdGhlIGtleSAocGlja2VkIGJ5IHNoYXJkIGxhdGVuY3ksXG4gICAgICogc2VlIEFyY2hpdmVzQ2hhaW4pIGFuZCB0aGUgY2FsbGVyIG5lZWRzIHRoZSByZXR1cm5lZCBrZXkgdG8gZXZlciByZWFkIHRoZSB2YWx1ZSBiYWNrLlxuICAgICAqL1xuICAgIC8qKlxuICAgICAqIFRIUk9XUyBvbiBhbiBlbXB0eSBidWZmZXI6IGFuIGVtcHR5IGZpbGUgSVMgYSBkZWxldGlvbiBpbiB0aGlzIHN5c3RlbSAodGhlIHRvbWJzdG9uZSksIHNvIGFcbiAgICAgKiBzZXQtZW1wdHkgd291bGQgcmVhZCBiYWNrIGFzIFwidGhlIGZpbGUgaXMgZ29uZVwiIC0gd2hpY2ggaXMganVzdCBhc2tpbmcgZm9yIHByb2JsZW1zLiBJZiB5b3VcbiAgICAgKiB3YW50IHRoZSBmaWxlIGRlbGV0ZWQsIGNhbGwgZGVsOyBkZWxldGlvbnMgdGFrZSB0aGVpciBvd24gcGF0aC5cbiAgICAgKi9cbiAgICBzZXQoZmlsZU5hbWU6IHN0cmluZywgZGF0YTogQnVmZmVyLCBjb25maWc/OiBTZXRDb25maWcpOiBQcm9taXNlPHN0cmluZz47XG4gICAgZGVsKGZpbGVOYW1lOiBzdHJpbmcsIGNvbmZpZz86IERlbENvbmZpZyk6IFByb21pc2U8dm9pZD47XG4gICAgLyoqIE1vdmVzIGEgZmlsZSB0byBhIG5ldyBwYXRoIHdpdGhpbiBUSElTIGFyY2hpdmVzLCBiYWNrZW5kLXNpZGUgd2hlcmUgdGhlIGJhY2tlbmQgY2FuIChiYWNrYmxhemUgY29waWVzIHNlcnZlci1zaWRlLCBkaXNrIHJlbmFtZXMsIHRoZSBzdG9yYWdlIHNlcnZlciByZWxvY2F0ZXMgbm9kZS1zaWRlKSAtIHRoZSBieXRlcyBuZXZlciB0cmF2ZWwgdGhyb3VnaCB0aGUgY2FsbGVyLiBUaGUgZGVzdGluYXRpb24gaXMgc3RhbXBlZCB3aXRoIGEgRlJFU0ggd3JpdGUgdGltZSwgZXZlbiB3aGVuIHRoZSB1bmRlcmx5aW5nIG9wZXJhdGlvbiAoYSByZW5hbWUpIHdvdWxkIHByZXNlcnZlIHRoZSBvbGQgb25lLCBzbyB0aGUgbW92ZWQgZmlsZSBjYW5ub3QgaW1tZWRpYXRlbHkgbG9zZSB0byBzb21ldGhpbmcgbmV3ZXIgc2l0dGluZyBhdCBpdHMgbmV3IHBhdGggKGUuZy4gdGhlIHRvbWJzdG9uZSBvZiBhbiBlYXJsaWVyIGRlbGV0aW9uIHRoZXJlKTsgdGhlIHNvdXJjZSBpcyB0aGVuIGRlbGV0ZWQsIGV4YWN0bHkgbGlrZSBkZWwuIFRIUk9XUyB3aGVuIHRoZSBzb3VyY2UgZmlsZSBkb2VzIG5vdCBleGlzdC4gT3B0aW9uYWwgLSBjYWxsZXJzIGdvIHRocm91Z2ggbW92ZUFyY2hpdmVGaWxlIChhcmNoaXZlSGVscGVycy50cyksIHdoaWNoIGZhbGxzIGJhY2sgdG8gY29weSArIGNvbmZpcm0gKyBkZWxldGUuICovXG4gICAgbW92ZT8oY29uZmlnOiBNb3ZlRmlsZUNvbmZpZyk6IFByb21pc2U8dm9pZD47XG4gICAgLyoqIFJlc3RvcmVzIGEgZGVsZXRlZCBmaWxlIHdob3NlIGJ5dGVzIGFyZSBzdGlsbCBpbiB0aGUgZGVsZXRpb24gaGlzdG9yeSAoc2VlIFNldENvbmZpZy51bmRlbGV0ZSwgd2hpY2ggdGhpcyByaWRlcyBvbikuIE9ubHkgaW5kZXgtYmFja2VkIHN0b3JlcyBrZWVwIGEgZGVsZXRpb24gaGlzdG9yeSwgc28gb25seSB0aGV5IHN1cHBvcnQgdGhpcy4gVEhST1dTIHdoZW4gdGhlcmUgaXMgbm90aGluZyB0byByZXN0b3JlLiAqL1xuICAgIHVuZGVsZXRlPyhmaWxlTmFtZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPjtcbiAgICAvKiogU3RyZWFtcyBhIGZpbGUgdG9vIGxhcmdlIHRvIGhvbGQgaW4gbWVtb3J5LiBnZXROZXh0RGF0YSByZXR1cm5zIHVuZGVmaW5lZCB3aGVuIGRvbmUuIFRoaXMgb25seSBuZWVkcyB0byBiZSBjYWxsZWQgd2hlbiB5b3UgQ0FOTk9UIG1hdGVyaWFsaXplIHRoZSBlbnRpcmUgZmlsZSBpbiBtZW1vcnkgLSBpZiB5b3UgY2FuLCBqdXN0IGNhbGwgc2V0OiBhYm92ZSBMQVJHRV9TRVRfVEhSRVNIT0xEIGl0IHN0cmVhbXMgdGhyb3VnaCBzZXRMYXJnZUZpbGUgaW50ZXJuYWxseSwga2VlcGluZyB0aGUgY2xpZW50IHJlc3BvbnNpdmUgYW5kIG5vdCBvdmVyd2hlbG1pbmcgdGhlIHNlcnZlci4gVGhlIHJlc3Qgb2YgdGhlIGNvbmZpZyBpcyBhIHBsYWluIFNldENvbmZpZyBhbmQgbWVhbnMgZXhhY3RseSB3aGF0IGl0IG1lYW5zIG9uIHNldCAodGhhdCBpcyB3aGF0IG1ha2VzIGEgbGFyZ2Ugc2V0IGJlaGF2ZSBsaWtlIGEgc21hbGwgb25lIGluc3RlYWQgb2YgcXVpZXRseSBsb3NpbmcgaW1tdXRhYmlsaXR5LCBvcmRlcmluZywgaW50ZXJuYWwsIG9yIGZhbGxiYWNrcyBzZW1hbnRpY3MgYXMgdGhlIGZpbGUgY3Jvc3NlcyB0aGUgdGhyZXNob2xkKTsgYmFja2VuZHMgdGhhdCBzdGFtcCB0aGVpciBvd24gdGltZXMgKGJhY2tibGF6ZSkgYWNjZXB0IGFuZCBpZ25vcmUgbGFzdE1vZGlmaWVkLiBUSFJPV1Mgd2hlbiB0aGUgc3RyZWFtIHByb2R1Y2VzIG5vIGRhdGEgYXQgYWxsIC0gc2FtZSBydWxlIGFzIHNldDogYW4gZW1wdHkgZmlsZSBJUyBhIGRlbGV0aW9uIGFuZCB3b3VsZCByZWFkIGJhY2sgYXMgbWlzc2luZy4gKi9cbiAgICBzZXRMYXJnZUZpbGUoY29uZmlnOiBTZXRMYXJnZUZpbGVDb25maWcpOiBQcm9taXNlPHZvaWQ+O1xuICAgIC8qKiB3cml0ZVRpbWUgaXMgdGhlIGxhc3Qtd3JpdGUgdGltZSDigJQgc2VlIEFyY2hpdmVGaWxlSW5mby5jcmVhdGVUaW1lLCB3aGljaCBpcyB0aGUgc2FtZSB2YWx1ZS4gdXJsIGFzIGluIGdldDIuIFNpemUtMCBlbnRyaWVzICh0b21ic3RvbmVzKSByZXBvcnQgdW5kZWZpbmVkIHVubGVzcyBjb25maWcuaW5jbHVkZVRvbWJzdG9uZXMuICovXG4gICAgZ2V0SW5mbyhmaWxlTmFtZTogc3RyaW5nLCBjb25maWc/OiBHZXRJbmZvQ29uZmlnKTogUHJvbWlzZTx7IHdyaXRlVGltZTogbnVtYmVyOyBzaXplOiBudW1iZXI7IHVybD86IHN0cmluZyB9IHwgdW5kZWZpbmVkPjtcbiAgICAvKipcbiAgICAgKiBFbXB0eSAoc2l6ZS0wKSBmaWxlcyBhcmUgTkVWRVIgcmV0dXJuZWQgYnkgaW5kZXgtYmFja2VkIHN0b3JlcyAoQmxvYlN0b3JlLCBhbmQgdGhlcmVmb3JlIHRoZVxuICAgICAqIGNoYWluKTogYW4gZW1wdHkgZmlsZSBJUyBhIG1pc3NpbmcgZmlsZSAtIHRoZSB0b21ic3RvbmUgb2YgYSBkZWxldGlvbi4gSWYgeW91IHdhbnQgYSBtYXJrZXJcbiAgICAgKiBmaWxlIHRoYXQgc2hvd3MgdXAgaW4gbGlzdGluZ3MsIGFkZCBzb21lIGNvbnRlbnQgdG8gaXQuIFJhdyBzb3VyY2VzIChkaXNrLCBiYWNrYmxhemUpIERPIGxpc3RcbiAgICAgKiB0aGVpciBlbXB0eSBmaWxlcyAtIHRoYXQgaXMgaG93IHNjYW5zIGxlYXJuIG9mIGRlbGV0aW9ucyAtIGJ1dCBub3RoaW5nIGJ1aWx0IG9uIHRoZSBpbmRleFxuICAgICAqIGV2ZXIgc3VyZmFjZXMgdGhlbS5cbiAgICAgKi9cbiAgICBmaW5kKHByZWZpeDogc3RyaW5nLCBjb25maWc/OiBGaW5kQ29uZmlnKTogUHJvbWlzZTxzdHJpbmdbXT47XG4gICAgLyoqIFNlZSBmaW5kIGZvciB0aGUgZW1wdHktZmlsZSAodG9tYnN0b25lKSBydWxlLiAqL1xuICAgIGZpbmRJbmZvKHByZWZpeDogc3RyaW5nLCBjb25maWc/OiBGaW5kQ29uZmlnKTogUHJvbWlzZTxBcmNoaXZlRmlsZUluZm9bXT47XG4gICAgLyoqIE9ubHkgd29ya3MgZm9yIHB1YmxpYyBidWNrZXRzIChwcml2YXRlIGJ1Y2tldHMgYXJlIEFQSS1hY2Nlc3Mgb25seSkuICovXG4gICAgZ2V0VVJMKHBhdGg6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPjtcbiAgICAvKiogVGhlIGJ1Y2tldCdzIGNvbmZpZ3VyYXRpb24sIHdoaWNoIHRlbGxzIHdoZXRoZXIgdGhlIG9wdGlvbmFsIGZ1bmN0aW9ucyBhcmUgc3VwcG9ydGVkLiAqL1xuICAgIGdldENvbmZpZygpOiBQcm9taXNlPEFyY2hpdmVzQ29uZmlnPjtcbiAgICAvKipcbiAgICAgKiBBbGwgZmlsZXMgY2hhbmdlZCBhZnRlciBjb25maWcudGltZSwgb3B0aW9uYWxseSByZXN0cmljdGVkIHRvIGtleXMgcm91dGluZyBpbnRvIG9uZSBvZlxuICAgICAqIGNvbmZpZy5yb3V0ZXMgKHVzZWQgYnkgc2Nhbm5pbmcsIHNvIHBhcnRpYWxseS1vdmVybGFwcGluZyBzaGFyZHMgb25seSByZWNlaXZlIHRoZWlyIHNsaWNlKS5cbiAgICAgKiBXaGVuIGdldENvbmZpZygpLnN1cHBvcnRzQ2hhbmdlc0FmdGVyLCB0aGlzIGlzIGJhY2tlZCBieSBhbiBpbmRleCAoZmFzdCwgYW5kIGRlbGV0aW9ucyBBUkVcbiAgICAgKiByZXBvcnRlZCwgYXMgc2l6ZS0wIHRvbWJzdG9uZSBlbnRyaWVzKS4gRXZlcnkgb3RoZXIgYmFja2VuZCBlbXVsYXRlcyBpdDogYSBmdWxsIGZpbmRJbmZvXG4gICAgICogbGlzdGluZyBmaWx0ZXJlZCBpbiBtZW1vcnkgLSBjb3JyZWN0LCBidXQgbm8gY2hlYXBlciB0aGFuIHRoZSBsaXN0aW5nIGl0c2VsZi5cbiAgICAgKi9cbiAgICBnZXRDaGFuZ2VzQWZ0ZXIyKGNvbmZpZzogQ2hhbmdlc0FmdGVyQ29uZmlnKTogUHJvbWlzZTxBcmNoaXZlRmlsZUluZm9bXT47XG4gICAgLyoqIFN5bmNocm9uaXphdGlvbiBpbnRyb3NwZWN0aW9uLCBmb3IgYmFja2VuZHMgdGhhdCBzeW5jaHJvbml6ZSBmcm9tIHNvdXJjZXMgKHNlZSBCbG9iU3RvcmUpLiAqL1xuICAgIGdldFN5bmNTdGF0dXM/KCk6IFByb21pc2U8QXJjaGl2ZXNTeW5jU3RhdHVzPjtcbn1cbiJdfQ==
62
+ /* _JS_SOURCE_HASH = "994873b1a01467669341436b2bf49654f6ef04556f887f021f0b0bde3794a0ba"; */
@@ -180,13 +180,13 @@ export class ArchivesRemote implements IArchives {
180
180
  return await this.call(() => this.controller.getInfo({ account: this.account, bucketName: this.bucketName, path: fileName, sourceConfig: this.config.sourceConfig, includeTombstones: config?.includeTombstones }));
181
181
  }
182
182
  public async findInfo(prefix: string, config?: FindConfig): Promise<ArchiveFileInfo[]> {
183
- return await this.call(() => this.controller.findInfo({ account: this.account, bucketName: this.bucketName, prefix, sourceConfig: this.config.sourceConfig, shallow: config?.shallow, type: config?.type, includeMarked: config?.includeMarked }));
183
+ return await this.call(() => this.controller.findInfo({ account: this.account, bucketName: this.bucketName, prefix, sourceConfig: this.config.sourceConfig, shallow: config?.shallow, type: config?.type, includeMarked: config?.includeMarked, internal: config?.internal }));
184
184
  }
185
185
  public async find(prefix: string, config?: FindConfig): Promise<string[]> {
186
186
  return (await this.findInfo(prefix, config)).map(x => x.path);
187
187
  }
188
188
  public async getChangesAfter2(config: ChangesAfterConfig): Promise<ArchiveFileInfo[]> {
189
- return await this.call(() => this.controller.getChangesAfter2({ account: this.account, bucketName: this.bucketName, sourceConfig: this.config.sourceConfig, time: config.time, routes: config.routes }));
189
+ return await this.call(() => this.controller.getChangesAfter2({ account: this.account, bucketName: this.bucketName, sourceConfig: this.config.sourceConfig, time: config.time, routes: config.routes, internal: config.internal }));
190
190
  }
191
191
  public async getConfig(): Promise<ArchivesConfig> {
192
192
  return await this.call(() => this.controller.getArchivesConfig({ account: this.account, bucketName: this.bucketName }));
@@ -304,7 +304,7 @@ export declare class BlobStore {
304
304
  private assertFreshWriteTarget;
305
305
  private assertMutable;
306
306
  private assertInternalWriteAccepted;
307
- /** Internal (store-to-store) read: purely the local disk, completely short-circuiting the index and holder resolution - the caller is another store, and chasing OUR remote holders while answering it is how infinite get loops between stores form. No window or route checks: if the bytes are on our disk, the caller may have them. Note this reads the disk past any write delay, so a fast write still buffered in memory is invisible here; the caller re-finds it once it flushes. */
307
+ /** Internal (store-to-store) read: never goes to OTHER sources - the caller is another store, and chasing OUR remote holders while answering it is how infinite get loops between stores form - but the INDEX still gates, because it is the source of truth: a marked deletion keeps its bytes on disk as history (see writeToSources), so the disk alone would happily serve a DELETED file as live. Index says live -> the disk provides the bytes (past any write delay, so a fast write still buffered in memory is invisible here; the caller re-finds it once it flushes). Index says deleted -> the tombstone is the answer, never the disk. No window or route checks. */
308
308
  private getInternal2;
309
309
  /** Internal (store-to-store) write: the local disk plus our index, with NO downstream fan-out - the pushing store owns propagation, and fanning its pushes back out is how write loops between stores form. Only-take-latest still applies here. */
310
310
  private setInternal;
@@ -476,6 +476,8 @@ export class BlobStore {
476
476
  // Deletions are not in here at all, which is what a listing wants: an empty file IS a missing file
477
477
  for (let [key, entry] of this.indexEntries()) {
478
478
  if (!key.startsWith(prefix)) continue;
479
+ // See FindConfig.internal: an entry held by one of our OTHER sources cannot be served to a peer's internal read, so it must not be listed to one either
480
+ if (config.internal && this.slotForSourcesListIndex(entry.sourcesListIndex) !== 0) continue;
479
481
  infos.set(key, { path: key, createTime: entry.writeTime, size: entry.size });
480
482
  }
481
483
  if (config.includeMarked) {
@@ -499,6 +501,8 @@ export class BlobStore {
499
501
  for (let [key, entry] of this.indexEntries()) {
500
502
  if (entry.changedAt <= config.time) continue;
501
503
  if (!inRoutes(key)) continue;
504
+ // See ChangesAfterConfig.internal (deletions below are always reported - they are index-only)
505
+ if (config.internal && this.slotForSourcesListIndex(entry.sourcesListIndex) !== 0) continue;
502
506
  files.push({ path: key, createTime: entry.writeTime, size: entry.size });
503
507
  }
504
508
  for (let [key, tombstone] of this.deletedEntries()) {
@@ -1009,18 +1013,20 @@ export class BlobStore {
1009
1013
  }
1010
1014
  }
1011
1015
 
1012
- /** Internal (store-to-store) read: purely the local disk, completely short-circuiting the index and holder resolution - the caller is another store, and chasing OUR remote holders while answering it is how infinite get loops between stores form. No window or route checks: if the bytes are on our disk, the caller may have them. Note this reads the disk past any write delay, so a fast write still buffered in memory is invisible here; the caller re-finds it once it flushes. */
1016
+ /** Internal (store-to-store) read: never goes to OTHER sources - the caller is another store, and chasing OUR remote holders while answering it is how infinite get loops between stores form - but the INDEX still gates, because it is the source of truth: a marked deletion keeps its bytes on disk as history (see writeToSources), so the disk alone would happily serve a DELETED file as live. Index says live -> the disk provides the bytes (past any write delay, so a fast write still buffered in memory is invisible here; the caller re-finds it once it flushes). Index says deleted -> the tombstone is the answer, never the disk. No window or route checks. */
1013
1017
  private async getInternal2(config: { path: string; range?: { start: number; end: number }; includeTombstones?: boolean }): Promise<{ data: Buffer; writeTime: number; size: number } | undefined> {
1014
1018
  await this.init();
1015
- // includeTombstones forwards to the disk: a flag-caller (a peer store's synchronization) needs to see our deletions, not just our content. A tombstone deleted from disk entirely only lives in our index, so fall back to that.
1016
- let result = await this.getDiskSource().disk.get2(config.path, { range: config.range, includeTombstones: config.includeTombstones });
1017
- if (!result || !result.data) {
1019
+ let key = config.path;
1020
+ if (!this.getIndexEntry(key)) {
1021
+ // Deleted, or never here: a flag-caller (a peer store's synchronization) needs to see our deletions, not just our content
1018
1022
  if (config.includeTombstones) {
1019
- let deleted = this.getDeletedEntry(config.path);
1023
+ let deleted = this.getDeletedEntry(key);
1020
1024
  if (deleted) return { data: Buffer.alloc(0), writeTime: deleted.writeTime, size: 0 };
1021
1025
  }
1022
1026
  return undefined;
1023
1027
  }
1028
+ let result = await this.getDiskSource().disk.get2(key, { range: config.range });
1029
+ if (!result || !result.data) return undefined;
1024
1030
  return { data: result.data, writeTime: result.writeTime, size: result.size };
1025
1031
  }
1026
1032
 
@@ -394,14 +394,23 @@ export async function writeRoutingToAllStores(config: { configured: RemoteConfig
394
394
  let routingData = serializeRemoteConfig(configured);
395
395
  let routingWriteTime = Math.round(Date.now());
396
396
  let targets: SourceWrapper[] = [];
397
+ let skipped: SourceWrapper[] = [];
397
398
  let seen = new Set<string>();
398
399
  for (let source of sources) {
399
400
  let key = `${source.config.url}|${source.config.name}`;
400
401
  if (seen.has(key)) continue;
401
402
  seen.add(key);
403
+ // writeBlocked is a capability of this process (read-only mode, a browser, no backblaze credentials) - not connectivity, so skipping is not a pre-check race. Counting these as failures put the retry loop on its 5-minute cadence FOREVER over writes this process cannot make; the stores get the config from the writers that can (servers, node clients, peers pulling it from each other). The recheck first: the backblaze-credentials block can be a TRANSIENT secret-load failure at startup, and skipping on the stale verdict would otherwise make it permanent (see SourceWrapper.recheckWriteBlocked).
404
+ if (source.writeBlocked) {
405
+ await source.recheckWriteBlocked();
406
+ }
407
+ if (source.writeBlocked || !source.api) {
408
+ skipped.push(source);
409
+ continue;
410
+ }
402
411
  targets.push(source);
403
412
  }
404
- console.log(`Writing routing config version ${getConfigVersion(configured)} for ${debugName} to all ${targets.length} stores (write time ${formatDateTimeDetailed(routingWriteTime)}): ${targets.map(x => `${x.config.url} (store ${JSON.stringify(x.config.name)})`).join(", ")}`);
413
+ console.log(`Writing routing config version ${getConfigVersion(configured)} for ${debugName} to all ${targets.length} writable stores (write time ${formatDateTimeDetailed(routingWriteTime)}): ${targets.map(x => `${x.config.url} (store ${JSON.stringify(x.config.name)})`).join(", ") || "none"}${skipped.length && `. Skipping ${skipped.length} not writable from this process: ${skipped.map(x => `${x.config.url} (store ${JSON.stringify(x.config.name)}, ${x.writeBlocked || "no API access"})`).join(", ")}` || ""}`);
405
414
  let failures: string[] = [];
406
415
  await Promise.all(targets.map(async source => {
407
416
  try {