public inbox for [email protected]  
help / color / mirror / Atom feed
From: Tomas Vondra <[email protected]>
Subject: [PATCH 8/8] batch build
Date: Fri, 22 Jan 2021 01:11:08 +0100

---
 src/backend/access/brin/brin_minmax_multi.c | 204 ++++++++++++++++++--
 src/backend/access/brin/brin_tuple.c        |   1 +
 src/include/access/brin_tuple.h             |   2 +-
 3 files changed, 186 insertions(+), 21 deletions(-)

diff --git a/src/backend/access/brin/brin_minmax_multi.c b/src/backend/access/brin/brin_minmax_multi.c
index 094ecd2be9..72cca6f26b 100644
--- a/src/backend/access/brin/brin_minmax_multi.c
+++ b/src/backend/access/brin/brin_minmax_multi.c
@@ -57,6 +57,7 @@
 #include "access/brin.h"
 #include "access/brin_internal.h"
 #include "access/brin_tuple.h"
+#include "access/hash.h"	/* XXX strange that it fails because of BRIN_AM_OID without this */
 #include "access/reloptions.h"
 #include "access/stratnum.h"
 #include "access/htup_details.h"
@@ -150,12 +151,23 @@ typedef struct MinMaxOptions
 typedef struct Ranges
 {
 	Oid		typid;
+	Oid		colloid;
+	AttrNumber	attno;
 
 	/* (2*nranges + nvalues) <= maxvalues */
 	int		nranges;	/* number of ranges in the array (stored) */
 	int		nvalues;	/* number of values in the data array (all) */
 	int		maxvalues;	/* maximum number of values (reloption) */
 
+	/*
+	 * Batch mode means we're simply appending values into new range,
+	 * without any expensive steps (sorting, deduplication, ...). The
+	 * buffer is sized to be much larger, but we keep the actual target
+	 * size so that when serializing values we can do the right thing.
+	 */
+	bool	batch_mode;
+	int		target_maxvalues;
+
 	/* values stored for this range - either raw values, or ranges */
 	Datum	values[FLEXIBLE_ARRAY_MEMBER];
 } Ranges;
@@ -375,6 +387,7 @@ range_deserialize(SerializedRanges *serialized)
 	range->nvalues = serialized->nvalues;
 	range->maxvalues = serialized->maxvalues;
 	range->typid = serialized->typid;
+	range->batch_mode = false;
 
 	typbyval = get_typbyval(serialized->typid);
 	typlen = get_typlen(serialized->typid);
@@ -844,11 +857,14 @@ fill_combine_ranges(CombineRange *cranges, int ncranges, Ranges *ranges)
 /*
  * Sort combine ranges using qsort (with BTLessStrategyNumber function).
  */
-static void
+static int
 sort_combine_ranges(FmgrInfo *cmp, Oid colloid,
-					CombineRange *cranges, int ncranges)
+					CombineRange *cranges, int ncranges,
+					bool deduplicate)
 {
-	compare_context cxt;
+	int				n;
+	int				i;
+	compare_context	cxt;
 
 	/* sort the values */
 	cxt.colloid = colloid;
@@ -856,6 +872,24 @@ sort_combine_ranges(FmgrInfo *cmp, Oid colloid,
 
 	qsort_arg(cranges, ncranges, sizeof(CombineRange),
 			  compare_combine_ranges, (void *) &cxt);
+
+	if (!deduplicate)
+		return ncranges;
+
+	/* optionally deduplicate the ranges */
+	n = 1;
+	for (i = 1; i < ncranges; i++)
+	{
+		if (compare_combine_ranges(&cranges[i-1], &cranges[i], (void *) &cxt))
+		{
+			if (i != n)
+				memcpy(&cranges[n], &cranges[i], sizeof(CombineRange));
+
+			n++;
+		}
+	}
+
+	return n;
 }
 
 /*
@@ -1026,26 +1060,40 @@ build_distances(FmgrInfo *distanceFn, Oid colloid,
  */
 static CombineRange *
 build_combine_ranges(FmgrInfo *cmp, Oid colloid, Ranges *ranges,
-					 Datum newvalue, int *nranges)
+					 bool addvalue, Datum newvalue, int *nranges,
+					 bool deduplicate)
 {
 	int				ncranges;
 	CombineRange   *cranges;
 
 	/* now do the actual merge sort */
-	ncranges = ranges->nranges + ranges->nvalues + 1;
+	ncranges = ranges->nranges + ranges->nvalues;
+
+	/* should we add an extra value? */
+	if (addvalue)
+		ncranges += 1;
+
 	cranges = (CombineRange *) palloc0(ncranges * sizeof(CombineRange));
-	*nranges = ncranges;
 
 	/* put the new value at the beginning */
-	cranges[0].minval = newvalue;
-	cranges[0].maxval = newvalue;
-	cranges[0].collapsed = true;
+	if (addvalue)
+	{
+		cranges[0].minval = newvalue;
+		cranges[0].maxval = newvalue;
+		cranges[0].collapsed = true;
 
-	/* then the regular and collapsed ranges */
-	fill_combine_ranges(&cranges[1], ncranges-1, ranges);
+		/* then the regular and collapsed ranges */
+		fill_combine_ranges(&cranges[1], ncranges-1, ranges);
+	}
+	else
+		fill_combine_ranges(cranges, ncranges, ranges);
 
 	/* and sort the ranges */
-	sort_combine_ranges(cmp, colloid, cranges, ncranges);
+	ncranges = sort_combine_ranges(cmp, colloid, cranges, ncranges,
+								   deduplicate);
+
+	/* remember how many cranges we built */
+	*nranges = ncranges;
 
 	return cranges;
 }
@@ -1074,6 +1122,7 @@ count_values(CombineRange *cranges, int ncranges)
 }
 #endif
 
+
 /*
  * reduce_combine_ranges
  *		reduce the ranges until the number of values is low enough
@@ -1250,6 +1299,25 @@ range_add_value(BrinDesc *bdesc, Oid colloid,
 
 	Assert(2*ranges->nranges + ranges->nvalues <= ranges->maxvalues);
 
+	Assert((ranges->nranges >= 0) && (ranges->nvalues >= 0) && (ranges->maxvalues >= 0));
+
+	/*
+	 * When batch-building, there should be no ranges. So either the
+	 * number of ranges is 0 or we're not in batching mode.
+	 */
+	Assert(!ranges->batch_mode || (ranges->nranges == 0));
+
+	/* When batch-building, just add it and we're done. */
+	if (ranges->batch_mode)
+	{
+		/* there has to be free space, if we've sized the struct */
+		Assert(ranges->nvalues < ranges->maxvalues);
+
+		ranges->values[ranges->nvalues++] = newval;
+
+		return true;
+	}
+
 	/*
 	 * Bail out if the value already is covered by the range.
 	 *
@@ -1322,7 +1390,9 @@ range_add_value(BrinDesc *bdesc, Oid colloid,
 					 ranges->nvalues);
 
 	/* OK build the combine ranges */
-	cranges = build_combine_ranges(cmpFn, colloid, ranges, newval, &ncranges);
+	cranges = build_combine_ranges(cmpFn, colloid, ranges,
+								   true, newval, &ncranges,
+								   false);
 
 	/* Reduce the ranges if needed */
 	if (ncranges > ranges->maxvalues)
@@ -1382,6 +1452,81 @@ range_add_value(BrinDesc *bdesc, Oid colloid,
 	return true;
 }
 
+/*
+ * Generate range representation of data collected during "batch mode".
+ * This is similar to reduce_combine_ranges, except that we can't assume
+ * the values are sorted and there may be duplicate values.
+ */
+static void
+compactify_ranges(BrinDesc *bdesc, Ranges *ranges, int max_values)
+{
+	FmgrInfo   *cmpFn,
+			   *distanceFn;
+
+	/* combine ranges */
+	CombineRange   *cranges;
+	int				ncranges;
+	DistanceValue  *distances;
+
+	MemoryContext	ctx;
+	MemoryContext	oldctx;
+
+	/*
+	 * This should only be used in batch mode, and there should be no
+	 * ranges, just individual values.
+	 */
+	Assert((ranges->batch_mode) && (ranges->nranges == 0));
+
+	/* we'll certainly need the comparator, so just look it up now */
+	cmpFn = minmax_multi_get_strategy_procinfo(bdesc, ranges->attno, ranges->typid,
+											   BTLessStrategyNumber);
+
+	/* and we'll also need the 'distance' procedure */
+	distanceFn = minmax_multi_get_procinfo(bdesc, ranges->attno, PROCNUM_DISTANCE);
+
+	/*
+	 * The distanceFn calls (which may internally call e.g. numeric_le) may
+	 * allocate quite a bit of memory, and we must not leak it. Otherwise
+	 * we'd have problems e.g. when building indexes. So we create a local
+	 * memory context and make sure we free the memory before leaving this
+	 * function (not after every call).
+	 */
+	ctx = AllocSetContextCreate(CurrentMemoryContext,
+								"minmax-multi context",
+								ALLOCSET_DEFAULT_SIZES);
+
+	oldctx = MemoryContextSwitchTo(ctx);
+
+	/* OK build the combine ranges */
+	cranges = build_combine_ranges(cmpFn, ranges->colloid, ranges,
+								   false, (Datum) 0, &ncranges,
+								   true);	/* deduplicate */
+
+	/* build array of gap distances and sort them in ascending order */
+	distances = build_distances(distanceFn, ranges->colloid, cranges, ncranges);
+
+	/*
+	 * Combine ranges until we get below max_values. We don't use any scale
+	 * factor, because this is used at the very end of "batch mode" and we
+	 * don't expect more tuples to be inserted soon.
+	 */
+	ncranges = reduce_combine_ranges(cranges, ncranges, distances,
+									  max_values, cmpFn, ranges->colloid);
+
+	Assert(count_values(cranges, ncranges) <= max_values);
+
+	/* decompose the combine ranges into regular ranges and single values */
+	store_combine_ranges(ranges, cranges, ncranges);
+
+	MemoryContextSwitchTo(oldctx);
+	MemoryContextDelete(ctx);
+
+	/* Check the ordering invariants are not violated (for both parts). */
+	AssertArrayOrder(cmpFn, ranges->colloid, ranges->values, ranges->nranges*2);
+	AssertArrayOrder(cmpFn, ranges->colloid, &ranges->values[ranges->nranges*2],
+					 ranges->nvalues);
+}
+
 Datum
 brin_minmax_multi_opcinfo(PG_FUNCTION_ARGS)
 {
@@ -1799,10 +1944,16 @@ brin_minmax_multi_distance_inet(PG_FUNCTION_ARGS)
 }
 
 static void
-brin_minmax_multi_serialize(Datum src, Datum *dst)
+brin_minmax_multi_serialize(BrinDesc *bdesc, Datum src, Datum *dst)
 {
 	Ranges *ranges = (Ranges *) DatumGetPointer(src);
-	SerializedRanges *s = range_serialize(ranges);
+	SerializedRanges *s;
+
+	/* In batch mode, we need to compress the accumulated values. */
+	if (ranges->batch_mode)
+		compactify_ranges(bdesc, ranges, ranges->target_maxvalues);
+
+	s = range_serialize(ranges);
 	dst[0] = PointerGetDatum(s);
 }
 
@@ -1845,15 +1996,28 @@ brin_minmax_multi_add_value(PG_FUNCTION_ARGS)
 	/*
 	 * If this is the first non-null value, we need to initialize the range
 	 * list. Otherwise just extract the existing range list from BrinValues.
+	 *
+	 * When starting with an empty range, we assume this is a batch mode,
+	 * i.e. we size the buffer for the maximum possible number of items in
+	 * the range (based on range size and max number of items on a page).
+	 *
+	 * XXX This may require quite a bit of memory, so maybe we should use
+	 * some value in between. OTOH most tables will have much wider rows,
+	 * so the number of rows per page is much lower.
 	 */
 	if (column->bv_allnulls)
 	{
 		MemoryContext oldctx;
 
-		oldctx = MemoryContextSwitchTo(column->bv_context);
+		BlockNumber		pagesPerRange = BrinGetPagesPerRange(bdesc->bd_index);
 
-		ranges = minmax_multi_init(brin_minmax_multi_get_values(bdesc, opts));
+		oldctx = MemoryContextSwitchTo(column->bv_context);
+		ranges = minmax_multi_init(MaxHeapTuplesPerPage * pagesPerRange);
+		ranges->attno = attno;
+		ranges->colloid = colloid;
 		ranges->typid = attr->atttypid;
+		ranges->batch_mode = true;
+		ranges->target_maxvalues = brin_minmax_multi_get_values(bdesc, opts);
 
 		MemoryContextSwitchTo(oldctx);
 
@@ -2125,7 +2289,7 @@ brin_minmax_multi_union(PG_FUNCTION_ARGS)
 	oldctx = MemoryContextSwitchTo(ctx);
 
 	/* allocate and fill */
-	cranges = (CombineRange *)palloc0(ncranges * sizeof(CombineRange));
+	cranges = (CombineRange *) palloc0(ncranges * sizeof(CombineRange));
 
 	/* fill the combine ranges with entries for the first range */
 	fill_combine_ranges(cranges, ranges_a->nranges + ranges_a->nvalues,
@@ -2139,8 +2303,8 @@ brin_minmax_multi_union(PG_FUNCTION_ARGS)
 	cmpFn = minmax_multi_get_strategy_procinfo(bdesc, attno, attr->atttypid,
 											 BTLessStrategyNumber);
 
-	/* sort the combine ranges */
-	sort_combine_ranges(cmpFn, colloid, cranges, ncranges);
+	/* sort the combine ranges (don't deduplicate) */
+	sort_combine_ranges(cmpFn, colloid, cranges, ncranges, false);
 
 	/*
 	 * We've merged two different lists of ranges, so some of them may be
diff --git a/src/backend/access/brin/brin_tuple.c b/src/backend/access/brin/brin_tuple.c
index df820db029..bf8635d788 100644
--- a/src/backend/access/brin/brin_tuple.c
+++ b/src/backend/access/brin/brin_tuple.c
@@ -163,6 +163,7 @@ brin_form_tuple(BrinDesc *brdesc, BlockNumber blkno, BrinMemTuple *tuple,
 		if (tuple->bt_columns[keyno].bv_serialize)
 		{
 			tuple->bt_columns[keyno].bv_serialize(
+				brdesc,
 				tuple->bt_columns[keyno].bv_mem_value,
 				tuple->bt_columns[keyno].bv_values);
 		}
diff --git a/src/include/access/brin_tuple.h b/src/include/access/brin_tuple.h
index 66a6c3c792..e08998b71a 100644
--- a/src/include/access/brin_tuple.h
+++ b/src/include/access/brin_tuple.h
@@ -14,7 +14,7 @@
 #include "access/brin_internal.h"
 #include "access/tupdesc.h"
 
-typedef void (*brin_serialize_callback_type) (Datum src, Datum * dst);
+typedef void (*brin_serialize_callback_type) (BrinDesc *bdesc, Datum src, Datum * dst);
 
 /*
  * A BRIN index stores one index tuple per page range.  Each index tuple
-- 
2.26.2


--------------FA974B75A0C3E9CA18CE7207
Content-Type: application/x-shellscript;
 name="brin.sh"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
 filename="brin.sh"

IyEvdXNyL2Jpbi9iYXNoCgpOUk9XUz0kMQoKZHJvcGRiIC0taWYtZXhpc3RzIHRlc3QKY3Jl
YXRlZGIgdGVzdAoKIyBtb25vdG9uaWMsIGFzY2VuZGluZywgaW50NAoKcHNxbCB0ZXN0IC1j
ICJjcmVhdGUgdW5sb2dnZWQgdGFibGUgdCAoYSBpbnQpIiA+IC9kZXYvbnVsbCAyPiYxCnBz
cWwgdGVzdCAtYyAiaW5zZXJ0IGludG8gdCBzZWxlY3QgaSBmcm9tIGdlbmVyYXRlX3Nlcmll
cygxLCROUk9XUykgcyhpKSIgPiAvZGV2L251bGwgMj4mMQpwc3FsIHRlc3QgLWMgInZhY3V1
bSBhbmFseXplIHQiID4gL2Rldi9udWxsIDI+JjEKcHNxbCB0ZXN0IC1jICJjaGVja3BvaW50
IiA+IC9kZXYvbnVsbCAyPiYxCgpmb3IgciBpbiBgc2VxIDEgMTBgOyBkbwoKCSMgcmVndWxh
ciBidHJlZSBpbmRleAoJcHNxbCB0ZXN0ID4gYnJpbi50bXAgPDxFT0YKXHRpbWluZwpjcmVh
dGUgaW5kZXggaWR4IG9uIHQgKGEpOwpkcm9wIGluZGV4IGlkeDsKRU9GCgoJdD1gZ3JlcCBU
aW1lIGJyaW4udG1wIHwgaGVhZCAtbiAxIHwgYXdrICd7cHJpbnQgJDJ9J2AKCgllY2hvIG1v
bm90b25pYy1hc2MgaW50NCBidHJlZSAkciAkdAoKCSMgYnJpbiBtaW5tYXggaW5kZXgKCXBz
cWwgdGVzdCA+IGJyaW4udG1wIDw8RU9GClx0aW1pbmcKY3JlYXRlIGluZGV4IGlkeCBvbiB0
IHVzaW5nIGJyaW4gKGEpOwpkcm9wIGluZGV4IGlkeDsKRU9GCgoJdD1gZ3JlcCBUaW1lIGJy
aW4udG1wIHwgaGVhZCAtbiAxIHwgYXdrICd7cHJpbnQgJDJ9J2AKCgllY2hvIG1vbm90b25p
Yy1hc2MgaW50NCBicmluLW1pbm1heCAkciAkdAoKCSMgYnJpbiBtdWx0aSBtaW5tYXggaW5k
ZXgKCXBzcWwgdGVzdCA+IGJyaW4udG1wIDw8RU9GClx0aW1pbmcKY3JlYXRlIGluZGV4IGlk
eCBvbiB0IHVzaW5nIGJyaW4gKGEgaW50NF9taW5tYXhfbXVsdGlfb3BzKTsKZHJvcCBpbmRl
eCBpZHg7CkVPRgoKCXQ9YGdyZXAgVGltZSBicmluLnRtcCB8IGhlYWQgLW4gMSB8IGF3ayAn
e3ByaW50ICQyfSdgCgoJZWNobyBtb25vdG9uaWMtYXNjIGludDQgYnJpbi1tdWx0aS1taW5t
YXggJHIgJHQKCgkjIGJyaW4gYmxvb20gaW5kZXgKCXBzcWwgdGVzdCA+IGJyaW4udG1wIDw8
RU9GClx0aW1pbmcKY3JlYXRlIGluZGV4IGlkeCBvbiB0IHVzaW5nIGJyaW4gKGEgaW50NF9i
bG9vbV9vcHMpOwpkcm9wIGluZGV4IGlkeDsKRU9GCgoJdD1gZ3JlcCBUaW1lIGJyaW4udG1w
IHwgaGVhZCAtbiAxIHwgYXdrICd7cHJpbnQgJDJ9J2AKCgllY2hvIG1vbm90b25pYy1hc2Mg
aW50NCBicmluLWJsb29tICRyICR0Cgpkb25lCgpwc3FsIHRlc3QgLWMgImRyb3AgdGFibGUg
dCIgPiAvZGV2L251bGwgMj4mMQoKCiMgbW9ub3RvbmljLCBhc2NlbmRpbmcsIGludDQsIHBh
ZGRlZAoKcHNxbCB0ZXN0IC1jICJjcmVhdGUgdW5sb2dnZWQgdGFibGUgdCAoYSBpbnQsIGIg
dGV4dCkiID4gL2Rldi9udWxsIDI+JjEKcHNxbCB0ZXN0IC1jICJpbnNlcnQgaW50byB0IHNl
bGVjdCBpLCBtZDUoaTo6dGV4dCkgZnJvbSBnZW5lcmF0ZV9zZXJpZXMoMSwkTlJPV1MpIHMo
aSkiID4gL2Rldi9udWxsIDI+JjEKcHNxbCB0ZXN0IC1jICJ2YWN1dW0gYW5hbHl6ZSB0IiA+
IC9kZXYvbnVsbCAyPiYxCnBzcWwgdGVzdCAtYyAiY2hlY2twb2ludCIgPiAvZGV2L251bGwg
Mj4mMQoKZm9yIHIgaW4gYHNlcSAxIDEwYDsgZG8KCgkjIHJlZ3VsYXIgYnRyZWUgaW5kZXgK
CXBzcWwgdGVzdCA+IGJyaW4udG1wIDw8RU9GClx0aW1pbmcKY3JlYXRlIGluZGV4IGlkeCBv
biB0IChhKTsKZHJvcCBpbmRleCBpZHg7CkVPRgoKCXQ9YGdyZXAgVGltZSBicmluLnRtcCB8
IGhlYWQgLW4gMSB8IGF3ayAne3ByaW50ICQyfSdgCgoJZWNobyBtb25vdG9uaWMtYXNjIGlu
dDQtcGFkZGVkIGJ0cmVlICRyICR0CgoJIyBicmluIG1pbm1heCBpbmRleAoJcHNxbCB0ZXN0
ID4gYnJpbi50bXAgPDxFT0YKXHRpbWluZwpjcmVhdGUgaW5kZXggaWR4IG9uIHQgdXNpbmcg
YnJpbiAoYSk7CmRyb3AgaW5kZXggaWR4OwpFT0YKCgl0PWBncmVwIFRpbWUgYnJpbi50bXAg
fCBoZWFkIC1uIDEgfCBhd2sgJ3twcmludCAkMn0nYAoKCWVjaG8gbW9ub3RvbmljLWFzYyBp
bnQ0LXBhZGRlZCBicmluLW1pbm1heCAkciAkdAoKCSMgYnJpbiBtdWx0aSBtaW5tYXggaW5k
ZXgKCXBzcWwgdGVzdCA+IGJyaW4udG1wIDw8RU9GClx0aW1pbmcKY3JlYXRlIGluZGV4IGlk
eCBvbiB0IHVzaW5nIGJyaW4gKGEgaW50NF9taW5tYXhfbXVsdGlfb3BzKTsKZHJvcCBpbmRl
eCBpZHg7CkVPRgoKCXQ9YGdyZXAgVGltZSBicmluLnRtcCB8IGhlYWQgLW4gMSB8IGF3ayAn
e3ByaW50ICQyfSdgCgoJZWNobyBtb25vdG9uaWMtYXNjIGludDQtcGFkZGVkIGJyaW4tbXVs
dGktbWlubWF4ICRyICR0CgoJIyBicmluIGJsb29tIGluZGV4Cglwc3FsIHRlc3QgPiBicmlu
LnRtcCA8PEVPRgpcdGltaW5nCmNyZWF0ZSBpbmRleCBpZHggb24gdCB1c2luZyBicmluIChh
IGludDRfYmxvb21fb3BzKTsKZHJvcCBpbmRleCBpZHg7CkVPRgoKCXQ9YGdyZXAgVGltZSBi
cmluLnRtcCB8IGhlYWQgLW4gMSB8IGF3ayAne3ByaW50ICQyfSdgCgoJZWNobyBtb25vdG9u
aWMtYXNjIGludDQtcGFkZGVkIGJyaW4tYmxvb20gJHIgJHQKCmRvbmUKCnBzcWwgdGVzdCAt
YyAiZHJvcCB0YWJsZSB0IiA+IC9kZXYvbnVsbCAyPiYxCgoKIyBtb25vdG9uaWMsIGRlc2Nl
bmRpbmcsIGludDQKCnBzcWwgdGVzdCAtYyAiY3JlYXRlIHVubG9nZ2VkIHRhYmxlIHQgKGEg
aW50KSIgPiAvZGV2L251bGwgMj4mMQpwc3FsIHRlc3QgLWMgImluc2VydCBpbnRvIHQgc2Vs
ZWN0IGkgZnJvbSBnZW5lcmF0ZV9zZXJpZXMoJE5ST1dTLDEsLTEpIHMoaSkiID4gL2Rldi9u
dWxsIDI+JjEKcHNxbCB0ZXN0IC1jICJ2YWN1dW0gYW5hbHl6ZSB0IiA+IC9kZXYvbnVsbCAy
PiYxCnBzcWwgdGVzdCAtYyAiY2hlY2twb2ludCIgPiAvZGV2L251bGwgMj4mMQoKZm9yIHIg
aW4gYHNlcSAxIDEwYDsgZG8KCgkjIHJlZ3VsYXIgYnRyZWUgaW5kZXgKCXBzcWwgdGVzdCA+
IGJyaW4udG1wIDw8RU9GClx0aW1pbmcKY3JlYXRlIGluZGV4IGlkeCBvbiB0IChhKTsKZHJv
cCBpbmRleCBpZHg7CkVPRgoKCXQ9YGdyZXAgVGltZSBicmluLnRtcCB8IGhlYWQgLW4gMSB8
IGF3ayAne3ByaW50ICQyfSdgCgoJZWNobyBtb25vdG9uaWMtZGVzYyBpbnQ0IGJ0cmVlICRy
ICR0CgoJIyBicmluIG1pbm1heCBpbmRleAoJcHNxbCB0ZXN0ID4gYnJpbi50bXAgPDxFT0YK
XHRpbWluZwpjcmVhdGUgaW5kZXggaWR4IG9uIHQgdXNpbmcgYnJpbiAoYSk7CmRyb3AgaW5k
ZXggaWR4OwpFT0YKCgl0PWBncmVwIFRpbWUgYnJpbi50bXAgfCBoZWFkIC1uIDEgfCBhd2sg
J3twcmludCAkMn0nYAoKCWVjaG8gbW9ub3RvbmljLWRlc2MgaW50NCBicmluLW1pbm1heCAk
ciAkdAoKCSMgYnJpbiBtdWx0aSBtaW5tYXggaW5kZXgKCXBzcWwgdGVzdCA+IGJyaW4udG1w
IDw8RU9GClx0aW1pbmcKY3JlYXRlIGluZGV4IGlkeCBvbiB0IHVzaW5nIGJyaW4gKGEgaW50
NF9taW5tYXhfbXVsdGlfb3BzKTsKZHJvcCBpbmRleCBpZHg7CkVPRgoKCXQ9YGdyZXAgVGlt
ZSBicmluLnRtcCB8IGhlYWQgLW4gMSB8IGF3ayAne3ByaW50ICQyfSdgCgoJZWNobyBtb25v
dG9uaWMtZGVzYyBpbnQ0IGJyaW4tbXVsdGktbWlubWF4ICRyICR0CgoJIyBicmluIGJsb29t
IGluZGV4Cglwc3FsIHRlc3QgPiBicmluLnRtcCA8PEVPRgpcdGltaW5nCmNyZWF0ZSBpbmRl
eCBpZHggb24gdCB1c2luZyBicmluIChhIGludDRfYmxvb21fb3BzKTsKZHJvcCBpbmRleCBp
ZHg7CkVPRgoKCXQ9YGdyZXAgVGltZSBicmluLnRtcCB8IGhlYWQgLW4gMSB8IGF3ayAne3By
aW50ICQyfSdgCgoJZWNobyBtb25vdG9uaWMtZGVzYyBpbnQ0IGJyaW4tYmxvb20gJHIgJHQK
CmRvbmUKCnBzcWwgdGVzdCAtYyAiZHJvcCB0YWJsZSB0IiA+IC9kZXYvbnVsbCAyPiYxCgoK
IyBtb25vdG9uaWMsIGRlc2NlbmRpbmcsIGludDQsIHBhZGRlZAoKcHNxbCB0ZXN0IC1jICJj
cmVhdGUgdW5sb2dnZWQgdGFibGUgdCAoYSBpbnQsIGIgdGV4dCkiID4gL2Rldi9udWxsIDI+
JjEKcHNxbCB0ZXN0IC1jICJpbnNlcnQgaW50byB0IHNlbGVjdCBpLCBtZDUoaTo6dGV4dCkg
ZnJvbSBnZW5lcmF0ZV9zZXJpZXMoJE5ST1dTLDEsLTEpIHMoaSkiID4gL2Rldi9udWxsIDI+
JjEKcHNxbCB0ZXN0IC1jICJ2YWN1dW0gYW5hbHl6ZSB0IiA+IC9kZXYvbnVsbCAyPiYxCnBz
cWwgdGVzdCAtYyAiY2hlY2twb2ludCIgPiAvZGV2L251bGwgMj4mMQoKZm9yIHIgaW4gYHNl
cSAxIDEwYDsgZG8KCgkjIHJlZ3VsYXIgYnRyZWUgaW5kZXgKCXBzcWwgdGVzdCA+IGJyaW4u
dG1wIDw8RU9GClx0aW1pbmcKY3JlYXRlIGluZGV4IGlkeCBvbiB0IChhKTsKZHJvcCBpbmRl
eCBpZHg7CkVPRgoKCXQ9YGdyZXAgVGltZSBicmluLnRtcCB8IGhlYWQgLW4gMSB8IGF3ayAn
e3ByaW50ICQyfSdgCgoJZWNobyBtb25vdG9uaWMtZGVzYyBpbnQ0LXBhZGRlZCBidHJlZSAk
ciAkdAoKCSMgYnJpbiBtaW5tYXggaW5kZXgKCXBzcWwgdGVzdCA+IGJyaW4udG1wIDw8RU9G
Clx0aW1pbmcKY3JlYXRlIGluZGV4IGlkeCBvbiB0IHVzaW5nIGJyaW4gKGEpOwpkcm9wIGlu
ZGV4IGlkeDsKRU9GCgoJdD1gZ3JlcCBUaW1lIGJyaW4udG1wIHwgaGVhZCAtbiAxIHwgYXdr
ICd7cHJpbnQgJDJ9J2AKCgllY2hvIG1vbm90b25pYy1kZXNjIGludDQtcGFkZGVkIGJyaW4t
bWlubWF4ICRyICR0CgoJIyBicmluIG11bHRpIG1pbm1heCBpbmRleAoJcHNxbCB0ZXN0ID4g
YnJpbi50bXAgPDxFT0YKXHRpbWluZwpjcmVhdGUgaW5kZXggaWR4IG9uIHQgdXNpbmcgYnJp
biAoYSBpbnQ0X21pbm1heF9tdWx0aV9vcHMpOwpkcm9wIGluZGV4IGlkeDsKRU9GCgoJdD1g
Z3JlcCBUaW1lIGJyaW4udG1wIHwgaGVhZCAtbiAxIHwgYXdrICd7cHJpbnQgJDJ9J2AKCgll
Y2hvIG1vbm90b25pYy1kZXNjIGludDQtcGFkZGVkIGJyaW4tbXVsdGktbWlubWF4ICRyICR0
CgoJIyBicmluIGJsb29tIGluZGV4Cglwc3FsIHRlc3QgPiBicmluLnRtcCA8PEVPRgpcdGlt
aW5nCmNyZWF0ZSBpbmRleCBpZHggb24gdCB1c2luZyBicmluIChhIGludDRfYmxvb21fb3Bz
KTsKZHJvcCBpbmRleCBpZHg7CkVPRgoKCXQ9YGdyZXAgVGltZSBicmluLnRtcCB8IGhlYWQg
LW4gMSB8IGF3ayAne3ByaW50ICQyfSdgCgoJZWNobyBtb25vdG9uaWMtZGVzYyBpbnQ0LXBh
ZGRlZCBicmluLWJsb29tICRyICR0Cgpkb25lCgpwc3FsIHRlc3QgLWMgImRyb3AgdGFibGUg
dCIgPiAvZGV2L251bGwgMj4mMQoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIG1vbm90b25pYywg
MTAwIGRpc3RpbmN0IHZhbHVlcywgaW50NAoKcHNxbCB0ZXN0IC1jICJjcmVhdGUgdW5sb2dn
ZWQgdGFibGUgdCAoYSBpbnQpIiA+IC9kZXYvbnVsbCAyPiYxCnBzcWwgdGVzdCAtYyAiaW5z
ZXJ0IGludG8gdCBzZWxlY3QgbW9kKGksMTAwKSBmcm9tIGdlbmVyYXRlX3NlcmllcygxLCRO
Uk9XUykgcyhpKSIgPiAvZGV2L251bGwgMj4mMQpwc3FsIHRlc3QgLWMgInZhY3V1bSBhbmFs
eXplIHQiID4gL2Rldi9udWxsIDI+JjEKcHNxbCB0ZXN0IC1jICJjaGVja3BvaW50IiA+IC9k
ZXYvbnVsbCAyPiYxCgpmb3IgciBpbiBgc2VxIDEgMTBgOyBkbwoKCSMgcmVndWxhciBidHJl
ZSBpbmRleAoJcHNxbCB0ZXN0ID4gYnJpbi50bXAgPDxFT0YKXHRpbWluZwpjcmVhdGUgaW5k
ZXggaWR4IG9uIHQgKGEpOwpkcm9wIGluZGV4IGlkeDsKRU9GCgoJdD1gZ3JlcCBUaW1lIGJy
aW4udG1wIHwgaGVhZCAtbiAxIHwgYXdrICd7cHJpbnQgJDJ9J2AKCgllY2hvIG1vbm90b25p
Yy0xMDAtYXNjIGludDQgYnRyZWUgJHIgJHQKCgkjIGJyaW4gbWlubWF4IGluZGV4Cglwc3Fs
IHRlc3QgPiBicmluLnRtcCA8PEVPRgpcdGltaW5nCmNyZWF0ZSBpbmRleCBpZHggb24gdCB1
c2luZyBicmluIChhKTsKZHJvcCBpbmRleCBpZHg7CkVPRgoKCXQ9YGdyZXAgVGltZSBicmlu
LnRtcCB8IGhlYWQgLW4gMSB8IGF3ayAne3ByaW50ICQyfSdgCgoJZWNobyBtb25vdG9uaWMt
MTAwLWFzYyBpbnQ0IGJyaW4tbWlubWF4ICRyICR0CgoJIyBicmluIG11bHRpIG1pbm1heCBp
bmRleAoJcHNxbCB0ZXN0ID4gYnJpbi50bXAgPDxFT0YKXHRpbWluZwpjcmVhdGUgaW5kZXgg
aWR4IG9uIHQgdXNpbmcgYnJpbiAoYSBpbnQ0X21pbm1heF9tdWx0aV9vcHMpOwpkcm9wIGlu
ZGV4IGlkeDsKRU9GCgoJdD1gZ3JlcCBUaW1lIGJyaW4udG1wIHwgaGVhZCAtbiAxIHwgYXdr
ICd7cHJpbnQgJDJ9J2AKCgllY2hvIG1vbm90b25pYy0xMDAtYXNjIGludDQgYnJpbi1tdWx0
aS1taW5tYXggJHIgJHQKCgkjIGJyaW4gYmxvb20gaW5kZXgKCXBzcWwgdGVzdCA+IGJyaW4u
dG1wIDw8RU9GClx0aW1pbmcKY3JlYXRlIGluZGV4IGlkeCBvbiB0IHVzaW5nIGJyaW4gKGEg
aW50NF9ibG9vbV9vcHMpOwpkcm9wIGluZGV4IGlkeDsKRU9GCgoJdD1gZ3JlcCBUaW1lIGJy
aW4udG1wIHwgaGVhZCAtbiAxIHwgYXdrICd7cHJpbnQgJDJ9J2AKCgllY2hvIG1vbm90b25p
Yy0xMDAtYXNjIGludDQgYnJpbi1ibG9vbSAkciAkdAoKZG9uZQoKcHNxbCB0ZXN0IC1jICJk
cm9wIHRhYmxlIHQiID4gL2Rldi9udWxsIDI+JjEKCgojIG1vbm90b25pYywgMTAwIHZhbHVl
cywgYXNjZW5kaW5nLCBpbnQ0LCBwYWRkZWQKCnBzcWwgdGVzdCAtYyAiY3JlYXRlIHVubG9n
Z2VkIHRhYmxlIHQgKGEgaW50LCBiIHRleHQpIiA+IC9kZXYvbnVsbCAyPiYxCnBzcWwgdGVz
dCAtYyAiaW5zZXJ0IGludG8gdCBzZWxlY3QgbW9kKGksMTAwKSwgbWQ1KGk6OnRleHQpIGZy
b20gZ2VuZXJhdGVfc2VyaWVzKDEsJE5ST1dTKSBzKGkpIiA+IC9kZXYvbnVsbCAyPiYxCnBz
cWwgdGVzdCAtYyAidmFjdXVtIGFuYWx5emUgdCIgPiAvZGV2L251bGwgMj4mMQpwc3FsIHRl
c3QgLWMgImNoZWNrcG9pbnQiID4gL2Rldi9udWxsIDI+JjEKCmZvciByIGluIGBzZXEgMSAx
MGA7IGRvCgoJIyByZWd1bGFyIGJ0cmVlIGluZGV4Cglwc3FsIHRlc3QgPiBicmluLnRtcCA8
PEVPRgpcdGltaW5nCmNyZWF0ZSBpbmRleCBpZHggb24gdCAoYSk7CmRyb3AgaW5kZXggaWR4
OwpFT0YKCgl0PWBncmVwIFRpbWUgYnJpbi50bXAgfCBoZWFkIC1uIDEgfCBhd2sgJ3twcmlu
dCAkMn0nYAoKCWVjaG8gbW9ub3RvbmljLTEwMC1hc2MgaW50NC1wYWRkZWQgYnRyZWUgJHIg
JHQKCgkjIGJyaW4gbWlubWF4IGluZGV4Cglwc3FsIHRlc3QgPiBicmluLnRtcCA8PEVPRgpc
dGltaW5nCmNyZWF0ZSBpbmRleCBpZHggb24gdCB1c2luZyBicmluIChhKTsKZHJvcCBpbmRl
eCBpZHg7CkVPRgoKCXQ9YGdyZXAgVGltZSBicmluLnRtcCB8IGhlYWQgLW4gMSB8IGF3ayAn
e3ByaW50ICQyfSdgCgoJZWNobyBtb25vdG9uaWMtMTAwLWFzYyBpbnQ0LXBhZGRlZCBicmlu
LW1pbm1heCAkciAkdAoKCSMgYnJpbiBtdWx0aSBtaW5tYXggaW5kZXgKCXBzcWwgdGVzdCA+
IGJyaW4udG1wIDw8RU9GClx0aW1pbmcKY3JlYXRlIGluZGV4IGlkeCBvbiB0IHVzaW5nIGJy
aW4gKGEgaW50NF9taW5tYXhfbXVsdGlfb3BzKTsKZHJvcCBpbmRleCBpZHg7CkVPRgoKCXQ9
YGdyZXAgVGltZSBicmluLnRtcCB8IGhlYWQgLW4gMSB8IGF3ayAne3ByaW50ICQyfSdgCgoJ
ZWNobyBtb25vdG9uaWMtMTAwLWFzYyBpbnQ0LXBhZGRlZCBicmluLW11bHRpLW1pbm1heCAk
ciAkdAoKCSMgYnJpbiBibG9vbSBpbmRleAoJcHNxbCB0ZXN0ID4gYnJpbi50bXAgPDxFT0YK
XHRpbWluZwpjcmVhdGUgaW5kZXggaWR4IG9uIHQgdXNpbmcgYnJpbiAoYSBpbnQ0X2Jsb29t
X29wcyk7CmRyb3AgaW5kZXggaWR4OwpFT0YKCgl0PWBncmVwIFRpbWUgYnJpbi50bXAgfCBo
ZWFkIC1uIDEgfCBhd2sgJ3twcmludCAkMn0nYAoKCWVjaG8gbW9ub3RvbmljLTEwMC1hc2Mg
aW50NC1wYWRkZWQgYnJpbi1ibG9vbSAkciAkdAoKZG9uZQoKcHNxbCB0ZXN0IC1jICJkcm9w
IHRhYmxlIHQiID4gL2Rldi9udWxsIDI+JjEKCgojIG1vbm90b25pYywgMTAwIGRpc3RpbmN0
IHZhbHVlcywgZGVzY2VuZGluZywgaW50NAoKcHNxbCB0ZXN0IC1jICJjcmVhdGUgdW5sb2dn
ZWQgdGFibGUgdCAoYSBpbnQpIiA+IC9kZXYvbnVsbCAyPiYxCnBzcWwgdGVzdCAtYyAiaW5z
ZXJ0IGludG8gdCBzZWxlY3QgbW9kKGksMTAwKSBmcm9tIGdlbmVyYXRlX3NlcmllcygkTlJP
V1MsMSwtMSkgcyhpKSIgPiAvZGV2L251bGwgMj4mMQpwc3FsIHRlc3QgLWMgInZhY3V1bSBh
bmFseXplIHQiID4gL2Rldi9udWxsIDI+JjEKcHNxbCB0ZXN0IC1jICJjaGVja3BvaW50IiA+
IC9kZXYvbnVsbCAyPiYxCgpmb3IgciBpbiBgc2VxIDEgMTBgOyBkbwoKCSMgcmVndWxhciBi
dHJlZSBpbmRleAoJcHNxbCB0ZXN0ID4gYnJpbi50bXAgPDxFT0YKXHRpbWluZwpjcmVhdGUg
aW5kZXggaWR4IG9uIHQgKGEpOwpkcm9wIGluZGV4IGlkeDsKRU9GCgoJdD1gZ3JlcCBUaW1l
IGJyaW4udG1wIHwgaGVhZCAtbiAxIHwgYXdrICd7cHJpbnQgJDJ9J2AKCgllY2hvIG1vbm90
b25pYy0xMDAtZGVzYyBpbnQ0IGJ0cmVlICRyICR0CgoJIyBicmluIG1pbm1heCBpbmRleAoJ
cHNxbCB0ZXN0ID4gYnJpbi50bXAgPDxFT0YKXHRpbWluZwpjcmVhdGUgaW5kZXggaWR4IG9u
IHQgdXNpbmcgYnJpbiAoYSk7CmRyb3AgaW5kZXggaWR4OwpFT0YKCgl0PWBncmVwIFRpbWUg
YnJpbi50bXAgfCBoZWFkIC1uIDEgfCBhd2sgJ3twcmludCAkMn0nYAoKCWVjaG8gbW9ub3Rv
bmljLTEwMC1kZXNjIGludDQgYnJpbi1taW5tYXggJHIgJHQKCgkjIGJyaW4gbXVsdGkgbWlu
bWF4IGluZGV4Cglwc3FsIHRlc3QgPiBicmluLnRtcCA8PEVPRgpcdGltaW5nCmNyZWF0ZSBp
bmRleCBpZHggb24gdCB1c2luZyBicmluIChhIGludDRfbWlubWF4X211bHRpX29wcyk7CmRy
b3AgaW5kZXggaWR4OwpFT0YKCgl0PWBncmVwIFRpbWUgYnJpbi50bXAgfCBoZWFkIC1uIDEg
fCBhd2sgJ3twcmludCAkMn0nYAoKCWVjaG8gbW9ub3RvbmljLTEwMC1kZXNjIGludDQgYnJp
bi1tdWx0aS1taW5tYXggJHIgJHQKCgkjIGJyaW4gYmxvb20gaW5kZXgKCXBzcWwgdGVzdCA+
IGJyaW4udG1wIDw8RU9GClx0aW1pbmcKY3JlYXRlIGluZGV4IGlkeCBvbiB0IHVzaW5nIGJy
aW4gKGEgaW50NF9ibG9vbV9vcHMpOwpkcm9wIGluZGV4IGlkeDsKRU9GCgoJdD1gZ3JlcCBU
aW1lIGJyaW4udG1wIHwgaGVhZCAtbiAxIHwgYXdrICd7cHJpbnQgJDJ9J2AKCgllY2hvIG1v
bm90b25pYy0xMDAtZGVzYyBpbnQ0IGJyaW4tYmxvb20gJHIgJHQKCmRvbmUKCnBzcWwgdGVz
dCAtYyAiZHJvcCB0YWJsZSB0IiA+IC9kZXYvbnVsbCAyPiYxCgoKIyBtb25vdG9uaWMsIDEw
MCBkaXN0aW5jdCB2YWx1ZXMsIGRlc2NlbmRpbmcsIGludDQsIHBhZGRlZAoKcHNxbCB0ZXN0
IC1jICJjcmVhdGUgdW5sb2dnZWQgdGFibGUgdCAoYSBpbnQsIGIgdGV4dCkiID4gL2Rldi9u
dWxsIDI+JjEKcHNxbCB0ZXN0IC1jICJpbnNlcnQgaW50byB0IHNlbGVjdCBtb2QoaSwgMTAw
KSwgbWQ1KGk6OnRleHQpIGZyb20gZ2VuZXJhdGVfc2VyaWVzKCROUk9XUywxLC0xKSBzKGkp
IiA+IC9kZXYvbnVsbCAyPiYxCnBzcWwgdGVzdCAtYyAidmFjdXVtIGFuYWx5emUgdCIgPiAv
ZGV2L251bGwgMj4mMQpwc3FsIHRlc3QgLWMgImNoZWNrcG9pbnQiID4gL2Rldi9udWxsIDI+
JjEKCmZvciByIGluIGBzZXEgMSAxMGA7IGRvCgoJIyByZWd1bGFyIGJ0cmVlIGluZGV4Cglw
c3FsIHRlc3QgPiBicmluLnRtcCA8PEVPRgpcdGltaW5nCmNyZWF0ZSBpbmRleCBpZHggb24g
dCAoYSk7CmRyb3AgaW5kZXggaWR4OwpFT0YKCgl0PWBncmVwIFRpbWUgYnJpbi50bXAgfCBo
ZWFkIC1uIDEgfCBhd2sgJ3twcmludCAkMn0nYAoKCWVjaG8gbW9ub3RvbmljLTEwMC1kZXNj
IGludDQtcGFkZGVkIGJ0cmVlICRyICR0CgoJIyBicmluIG1pbm1heCBpbmRleAoJcHNxbCB0
ZXN0ID4gYnJpbi50bXAgPDxFT0YKXHRpbWluZwpjcmVhdGUgaW5kZXggaWR4IG9uIHQgdXNp
bmcgYnJpbiAoYSk7CmRyb3AgaW5kZXggaWR4OwpFT0YKCgl0PWBncmVwIFRpbWUgYnJpbi50
bXAgfCBoZWFkIC1uIDEgfCBhd2sgJ3twcmludCAkMn0nYAoKCWVjaG8gbW9ub3RvbmljLTEw
MC1kZXNjIGludDQtcGFkZGVkIGJyaW4tbWlubWF4ICRyICR0CgoJIyBicmluIG11bHRpIG1p
bm1heCBpbmRleAoJcHNxbCB0ZXN0ID4gYnJpbi50bXAgPDxFT0YKXHRpbWluZwpjcmVhdGUg
aW5kZXggaWR4IG9uIHQgdXNpbmcgYnJpbiAoYSBpbnQ0X21pbm1heF9tdWx0aV9vcHMpOwpk
cm9wIGluZGV4IGlkeDsKRU9GCgoJdD1gZ3JlcCBUaW1lIGJyaW4udG1wIHwgaGVhZCAtbiAx
IHwgYXdrICd7cHJpbnQgJDJ9J2AKCgllY2hvIG1vbm90b25pYy0xMDAtZGVzYyBpbnQ0LXBh
ZGRlZCBicmluLW11bHRpLW1pbm1heCAkciAkdAoKCSMgYnJpbiBibG9vbSBpbmRleAoJcHNx
bCB0ZXN0ID4gYnJpbi50bXAgPDxFT0YKXHRpbWluZwpjcmVhdGUgaW5kZXggaWR4IG9uIHQg
dXNpbmcgYnJpbiAoYSBpbnQ0X2Jsb29tX29wcyk7CmRyb3AgaW5kZXggaWR4OwpFT0YKCgl0
PWBncmVwIFRpbWUgYnJpbi50bXAgfCBoZWFkIC1uIDEgfCBhd2sgJ3twcmludCAkMn0nYAoK
CWVjaG8gbW9ub3RvbmljLTEwMC1kZXNjIGludDQtcGFkZGVkIGJyaW4tYmxvb20gJHIgJHQK
CmRvbmUKCnBzcWwgdGVzdCAtYyAiZHJvcCB0YWJsZSB0IiA+IC9kZXYvbnVsbCAyPiYxCgoj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMKCiMgbW9ub3RvbmljLCAxMDAwMCBkaXN0aW5jdCB2YWx1ZXMs
IGludDQKCnBzcWwgdGVzdCAtYyAiY3JlYXRlIHVubG9nZ2VkIHRhYmxlIHQgKGEgaW50KSIg
PiAvZGV2L251bGwgMj4mMQpwc3FsIHRlc3QgLWMgImluc2VydCBpbnRvIHQgc2VsZWN0IG1v
ZChpLDEwMDAwKSBmcm9tIGdlbmVyYXRlX3NlcmllcygxLCROUk9XUykgcyhpKSIgPiAvZGV2
L251bGwgMj4mMQpwc3FsIHRlc3QgLWMgInZhY3V1bSBhbmFseXplIHQiID4gL2Rldi9udWxs
IDI+JjEKcHNxbCB0ZXN0IC1jICJjaGVja3BvaW50IiA+IC9kZXYvbnVsbCAyPiYxCgpmb3Ig
ciBpbiBgc2VxIDEgMTBgOyBkbwoKCSMgcmVndWxhciBidHJlZSBpbmRleAoJcHNxbCB0ZXN0
ID4gYnJpbi50bXAgPDxFT0YKXHRpbWluZwpjcmVhdGUgaW5kZXggaWR4IG9uIHQgKGEpOwpk
cm9wIGluZGV4IGlkeDsKRU9GCgoJdD1gZ3JlcCBUaW1lIGJyaW4udG1wIHwgaGVhZCAtbiAx
IHwgYXdrICd7cHJpbnQgJDJ9J2AKCgllY2hvIG1vbm90b25pYy0xMDAwMC1hc2MgaW50NCBi
dHJlZSAkciAkdAoKCSMgYnJpbiBtaW5tYXggaW5kZXgKCXBzcWwgdGVzdCA+IGJyaW4udG1w
IDw8RU9GClx0aW1pbmcKY3JlYXRlIGluZGV4IGlkeCBvbiB0IHVzaW5nIGJyaW4gKGEpOwpk
cm9wIGluZGV4IGlkeDsKRU9GCgoJdD1gZ3JlcCBUaW1lIGJyaW4udG1wIHwgaGVhZCAtbiAx
IHwgYXdrICd7cHJpbnQgJDJ9J2AKCgllY2hvIG1vbm90b25pYy0xMDAwMC1hc2MgaW50NCBi
cmluLW1pbm1heCAkciAkdAoKCSMgYnJpbiBtdWx0aSBtaW5tYXggaW5kZXgKCXBzcWwgdGVz
dCA+IGJyaW4udG1wIDw8RU9GClx0aW1pbmcKY3JlYXRlIGluZGV4IGlkeCBvbiB0IHVzaW5n
IGJyaW4gKGEgaW50NF9taW5tYXhfbXVsdGlfb3BzKTsKZHJvcCBpbmRleCBpZHg7CkVPRgoK
CXQ9YGdyZXAgVGltZSBicmluLnRtcCB8IGhlYWQgLW4gMSB8IGF3ayAne3ByaW50ICQyfSdg
CgoJZWNobyBtb25vdG9uaWMtMTAwMDAtYXNjIGludDQgYnJpbi1tdWx0aS1taW5tYXggJHIg
JHQKCgkjIGJyaW4gYmxvb20gaW5kZXgKCXBzcWwgdGVzdCA+IGJyaW4udG1wIDw8RU9GClx0
aW1pbmcKY3JlYXRlIGluZGV4IGlkeCBvbiB0IHVzaW5nIGJyaW4gKGEgaW50NF9ibG9vbV9v
cHMpOwpkcm9wIGluZGV4IGlkeDsKRU9GCgoJdD1gZ3JlcCBUaW1lIGJyaW4udG1wIHwgaGVh
ZCAtbiAxIHwgYXdrICd7cHJpbnQgJDJ9J2AKCgllY2hvIG1vbm90b25pYy0xMDAwMC1hc2Mg
aW50NCBicmluLWJsb29tICRyICR0Cgpkb25lCgpwc3FsIHRlc3QgLWMgImRyb3AgdGFibGUg
dCIgPiAvZGV2L251bGwgMj4mMQoKCiMgbW9ub3RvbmljLCAxMDAwMCB2YWx1ZXMsIGFzY2Vu
ZGluZywgaW50NCwgcGFkZGVkCgpwc3FsIHRlc3QgLWMgImNyZWF0ZSB1bmxvZ2dlZCB0YWJs
ZSB0IChhIGludCwgYiB0ZXh0KSIgPiAvZGV2L251bGwgMj4mMQpwc3FsIHRlc3QgLWMgImlu
c2VydCBpbnRvIHQgc2VsZWN0IG1vZChpLDEwMDAwKSwgbWQ1KGk6OnRleHQpIGZyb20gZ2Vu
ZXJhdGVfc2VyaWVzKDEsJE5ST1dTKSBzKGkpIiA+IC9kZXYvbnVsbCAyPiYxCnBzcWwgdGVz
dCAtYyAidmFjdXVtIGFuYWx5emUgdCIgPiAvZGV2L251bGwgMj4mMQpwc3FsIHRlc3QgLWMg
ImNoZWNrcG9pbnQiID4gL2Rldi9udWxsIDI+JjEKCmZvciByIGluIGBzZXEgMSAxMGA7IGRv
CgoJIyByZWd1bGFyIGJ0cmVlIGluZGV4Cglwc3FsIHRlc3QgPiBicmluLnRtcCA8PEVPRgpc
dGltaW5nCmNyZWF0ZSBpbmRleCBpZHggb24gdCAoYSk7CmRyb3AgaW5kZXggaWR4OwpFT0YK
Cgl0PWBncmVwIFRpbWUgYnJpbi50bXAgfCBoZWFkIC1uIDEgfCBhd2sgJ3twcmludCAkMn0n
YAoKCWVjaG8gbW9ub3RvbmljLTEwMDAwLWFzYyBpbnQ0LXBhZGRlZCBidHJlZSAkciAkdAoK
CSMgYnJpbiBtaW5tYXggaW5kZXgKCXBzcWwgdGVzdCA+IGJyaW4udG1wIDw8RU9GClx0aW1p
bmcKY3JlYXRlIGluZGV4IGlkeCBvbiB0IHVzaW5nIGJyaW4gKGEpOwpkcm9wIGluZGV4IGlk
eDsKRU9GCgoJdD1gZ3JlcCBUaW1lIGJyaW4udG1wIHwgaGVhZCAtbiAxIHwgYXdrICd7cHJp
bnQgJDJ9J2AKCgllY2hvIG1vbm90b25pYy0xMDAwMC1hc2MgaW50NC1wYWRkZWQgYnJpbi1t
aW5tYXggJHIgJHQKCgkjIGJyaW4gbXVsdGkgbWlubWF4IGluZGV4Cglwc3FsIHRlc3QgPiBi
cmluLnRtcCA8PEVPRgpcdGltaW5nCmNyZWF0ZSBpbmRleCBpZHggb24gdCB1c2luZyBicmlu
IChhIGludDRfbWlubWF4X211bHRpX29wcyk7CmRyb3AgaW5kZXggaWR4OwpFT0YKCgl0PWBn
cmVwIFRpbWUgYnJpbi50bXAgfCBoZWFkIC1uIDEgfCBhd2sgJ3twcmludCAkMn0nYAoKCWVj
aG8gbW9ub3RvbmljLTEwMDAwLWFzYyBpbnQ0LXBhZGRlZCBicmluLW11bHRpLW1pbm1heCAk
ciAkdAoKCSMgYnJpbiBibG9vbSBpbmRleAoJcHNxbCB0ZXN0ID4gYnJpbi50bXAgPDxFT0YK
XHRpbWluZwpjcmVhdGUgaW5kZXggaWR4IG9uIHQgdXNpbmcgYnJpbiAoYSBpbnQ0X2Jsb29t
X29wcyk7CmRyb3AgaW5kZXggaWR4OwpFT0YKCgl0PWBncmVwIFRpbWUgYnJpbi50bXAgfCBo
ZWFkIC1uIDEgfCBhd2sgJ3twcmludCAkMn0nYAoKCWVjaG8gbW9ub3RvbmljLTEwMDAwLWFz
YyBpbnQ0LXBhZGRlZCBicmluLWJsb29tICRyICR0Cgpkb25lCgpwc3FsIHRlc3QgLWMgImRy
b3AgdGFibGUgdCIgPiAvZGV2L251bGwgMj4mMQoKCiMgbW9ub3RvbmljLCAxMDAwMCBkaXN0
aW5jdCB2YWx1ZXMsIGRlc2NlbmRpbmcsIGludDQKCnBzcWwgdGVzdCAtYyAiY3JlYXRlIHVu
bG9nZ2VkIHRhYmxlIHQgKGEgaW50KSIgPiAvZGV2L251bGwgMj4mMQpwc3FsIHRlc3QgLWMg
Imluc2VydCBpbnRvIHQgc2VsZWN0IG1vZChpLDEwMDAwKSBmcm9tIGdlbmVyYXRlX3Nlcmll
cygkTlJPV1MsMSwtMSkgcyhpKSIgPiAvZGV2L251bGwgMj4mMQpwc3FsIHRlc3QgLWMgInZh
Y3V1bSBhbmFseXplIHQiID4gL2Rldi9udWxsIDI+JjEKcHNxbCB0ZXN0IC1jICJjaGVja3Bv
aW50IiA+IC9kZXYvbnVsbCAyPiYxCgpmb3IgciBpbiBgc2VxIDEgMTBgOyBkbwoKCSMgcmVn
dWxhciBidHJlZSBpbmRleAoJcHNxbCB0ZXN0ID4gYnJpbi50bXAgPDxFT0YKXHRpbWluZwpj
cmVhdGUgaW5kZXggaWR4IG9uIHQgKGEpOwpkcm9wIGluZGV4IGlkeDsKRU9GCgoJdD1gZ3Jl
cCBUaW1lIGJyaW4udG1wIHwgaGVhZCAtbiAxIHwgYXdrICd7cHJpbnQgJDJ9J2AKCgllY2hv
IG1vbm90b25pYy0xMDAwMC1kZXNjIGludDQgYnRyZWUgJHIgJHQKCgkjIGJyaW4gbWlubWF4
IGluZGV4Cglwc3FsIHRlc3QgPiBicmluLnRtcCA8PEVPRgpcdGltaW5nCmNyZWF0ZSBpbmRl
eCBpZHggb24gdCB1c2luZyBicmluIChhKTsKZHJvcCBpbmRleCBpZHg7CkVPRgoKCXQ9YGdy
ZXAgVGltZSBicmluLnRtcCB8IGhlYWQgLW4gMSB8IGF3ayAne3ByaW50ICQyfSdgCgoJZWNo
byBtb25vdG9uaWMtMTAwMDAtZGVzYyBpbnQ0IGJyaW4tbWlubWF4ICRyICR0CgoJIyBicmlu
IG11bHRpIG1pbm1heCBpbmRleAoJcHNxbCB0ZXN0ID4gYnJpbi50bXAgPDxFT0YKXHRpbWlu
ZwpjcmVhdGUgaW5kZXggaWR4IG9uIHQgdXNpbmcgYnJpbiAoYSBpbnQ0X21pbm1heF9tdWx0
aV9vcHMpOwpkcm9wIGluZGV4IGlkeDsKRU9GCgoJdD1gZ3JlcCBUaW1lIGJyaW4udG1wIHwg
aGVhZCAtbiAxIHwgYXdrICd7cHJpbnQgJDJ9J2AKCgllY2hvIG1vbm90b25pYy0xMDAwMC1k
ZXNjIGludDQgYnJpbi1tdWx0aS1taW5tYXggJHIgJHQKCgkjIGJyaW4gYmxvb20gaW5kZXgK
CXBzcWwgdGVzdCA+IGJyaW4udG1wIDw8RU9GClx0aW1pbmcKY3JlYXRlIGluZGV4IGlkeCBv
biB0IHVzaW5nIGJyaW4gKGEgaW50NF9ibG9vbV9vcHMpOwpkcm9wIGluZGV4IGlkeDsKRU9G
CgoJdD1gZ3JlcCBUaW1lIGJyaW4udG1wIHwgaGVhZCAtbiAxIHwgYXdrICd7cHJpbnQgJDJ9
J2AKCgllY2hvIG1vbm90b25pYy0xMDAwMC1kZXNjIGludDQgYnJpbi1ibG9vbSAkciAkdAoK
ZG9uZQoKcHNxbCB0ZXN0IC1jICJkcm9wIHRhYmxlIHQiID4gL2Rldi9udWxsIDI+JjEKCgoj
IG1vbm90b25pYywgMTAwMDAgZGlzdGluY3QgdmFsdWVzLCBkZXNjZW5kaW5nLCBpbnQ0LCBw
YWRkZWQKCnBzcWwgdGVzdCAtYyAiY3JlYXRlIHVubG9nZ2VkIHRhYmxlIHQgKGEgaW50LCBi
IHRleHQpIiA+IC9kZXYvbnVsbCAyPiYxCnBzcWwgdGVzdCAtYyAiaW5zZXJ0IGludG8gdCBz
ZWxlY3QgbW9kKGksIDEwMDAwKSwgbWQ1KGk6OnRleHQpIGZyb20gZ2VuZXJhdGVfc2VyaWVz
KCROUk9XUywxLC0xKSBzKGkpIiA+IC9kZXYvbnVsbCAyPiYxCnBzcWwgdGVzdCAtYyAidmFj
dXVtIGFuYWx5emUgdCIgPiAvZGV2L251bGwgMj4mMQpwc3FsIHRlc3QgLWMgImNoZWNrcG9p
bnQiID4gL2Rldi9udWxsIDI+JjEKCmZvciByIGluIGBzZXEgMSAxMGA7IGRvCgoJIyByZWd1
bGFyIGJ0cmVlIGluZGV4Cglwc3FsIHRlc3QgPiBicmluLnRtcCA8PEVPRgpcdGltaW5nCmNy
ZWF0ZSBpbmRleCBpZHggb24gdCAoYSk7CmRyb3AgaW5kZXggaWR4OwpFT0YKCgl0PWBncmVw
IFRpbWUgYnJpbi50bXAgfCBoZWFkIC1uIDEgfCBhd2sgJ3twcmludCAkMn0nYAoKCWVjaG8g
bW9ub3RvbmljLTEwMDAwLWRlc2MgaW50NC1wYWRkZWQgYnRyZWUgJHIgJHQKCgkjIGJyaW4g
bWlubWF4IGluZGV4Cglwc3FsIHRlc3QgPiBicmluLnRtcCA8PEVPRgpcdGltaW5nCmNyZWF0
ZSBpbmRleCBpZHggb24gdCB1c2luZyBicmluIChhKTsKZHJvcCBpbmRleCBpZHg7CkVPRgoK
CXQ9YGdyZXAgVGltZSBicmluLnRtcCB8IGhlYWQgLW4gMSB8IGF3ayAne3ByaW50ICQyfSdg
CgoJZWNobyBtb25vdG9uaWMtMTAwMDAtZGVzYyBpbnQ0LXBhZGRlZCBicmluLW1pbm1heCAk
ciAkdAoKCSMgYnJpbiBtdWx0aSBtaW5tYXggaW5kZXgKCXBzcWwgdGVzdCA+IGJyaW4udG1w
IDw8RU9GClx0aW1pbmcKY3JlYXRlIGluZGV4IGlkeCBvbiB0IHVzaW5nIGJyaW4gKGEgaW50
NF9taW5tYXhfbXVsdGlfb3BzKTsKZHJvcCBpbmRleCBpZHg7CkVPRgoKCXQ9YGdyZXAgVGlt
ZSBicmluLnRtcCB8IGhlYWQgLW4gMSB8IGF3ayAne3ByaW50ICQyfSdgCgoJZWNobyBtb25v
dG9uaWMtMTAwMDAtZGVzYyBpbnQ0LXBhZGRlZCBicmluLW11bHRpLW1pbm1heCAkciAkdAoK
CSMgYnJpbiBibG9vbSBpbmRleAoJcHNxbCB0ZXN0ID4gYnJpbi50bXAgPDxFT0YKXHRpbWlu
ZwpjcmVhdGUgaW5kZXggaWR4IG9uIHQgdXNpbmcgYnJpbiAoYSBpbnQ0X2Jsb29tX29wcyk7
CmRyb3AgaW5kZXggaWR4OwpFT0YKCgl0PWBncmVwIFRpbWUgYnJpbi50bXAgfCBoZWFkIC1u
IDEgfCBhd2sgJ3twcmludCAkMn0nYAoKCWVjaG8gbW9ub3RvbmljLTEwMDAwLWRlc2MgaW50
NC1wYWRkZWQgYnJpbi1ibG9vbSAkciAkdAoKZG9uZQoKcHNxbCB0ZXN0IC1jICJkcm9wIHRh
YmxlIHQiID4gL2Rldi9udWxsIDI+JjEKCiMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKIyByYW5kb20s
IDEwMCBkaXN0aW5jdCB2YWx1ZXMsIGludDQKCnBzcWwgdGVzdCAtYyAiY3JlYXRlIHVubG9n
Z2VkIHRhYmxlIHQgKGEgaW50KSIgPiAvZGV2L251bGwgMj4mMQpwc3FsIHRlc3QgLWMgImlu
c2VydCBpbnRvIHQgc2VsZWN0IDEwMCAqIHJhbmRvbSgpIGZyb20gZ2VuZXJhdGVfc2VyaWVz
KDEsJE5ST1dTKSBzKGkpIiA+IC9kZXYvbnVsbCAyPiYxCnBzcWwgdGVzdCAtYyAidmFjdXVt
IGFuYWx5emUgdCIgPiAvZGV2L251bGwgMj4mMQpwc3FsIHRlc3QgLWMgImNoZWNrcG9pbnQi
ID4gL2Rldi9udWxsIDI+JjEKCmZvciByIGluIGBzZXEgMSAxMGA7IGRvCgoJIyByZWd1bGFy
IGJ0cmVlIGluZGV4Cglwc3FsIHRlc3QgPiBicmluLnRtcCA8PEVPRgpcdGltaW5nCmNyZWF0
ZSBpbmRleCBpZHggb24gdCAoYSk7CmRyb3AgaW5kZXggaWR4OwpFT0YKCgl0PWBncmVwIFRp
bWUgYnJpbi50bXAgfCBoZWFkIC1uIDEgfCBhd2sgJ3twcmludCAkMn0nYAoKCWVjaG8gcmFu
ZG9tLTEwMCBpbnQ0IGJ0cmVlICRyICR0CgoJIyBicmluIG1pbm1heCBpbmRleAoJcHNxbCB0
ZXN0ID4gYnJpbi50bXAgPDxFT0YKXHRpbWluZwpjcmVhdGUgaW5kZXggaWR4IG9uIHQgdXNp
bmcgYnJpbiAoYSk7CmRyb3AgaW5kZXggaWR4OwpFT0YKCgl0PWBncmVwIFRpbWUgYnJpbi50
bXAgfCBoZWFkIC1uIDEgfCBhd2sgJ3twcmludCAkMn0nYAoKCWVjaG8gcmFuZG9tLTEwMCBp
bnQ0IGJyaW4tbWlubWF4ICRyICR0CgoJIyBicmluIG11bHRpIG1pbm1heCBpbmRleAoJcHNx
bCB0ZXN0ID4gYnJpbi50bXAgPDxFT0YKXHRpbWluZwpjcmVhdGUgaW5kZXggaWR4IG9uIHQg
dXNpbmcgYnJpbiAoYSBpbnQ0X21pbm1heF9tdWx0aV9vcHMpOwpkcm9wIGluZGV4IGlkeDsK
RU9GCgoJdD1gZ3JlcCBUaW1lIGJyaW4udG1wIHwgaGVhZCAtbiAxIHwgYXdrICd7cHJpbnQg
JDJ9J2AKCgllY2hvIHJhbmRvbS0xMDAgaW50NCBicmluLW11bHRpLW1pbm1heCAkciAkdAoK
CSMgYnJpbiBibG9vbSBpbmRleAoJcHNxbCB0ZXN0ID4gYnJpbi50bXAgPDxFT0YKXHRpbWlu
ZwpjcmVhdGUgaW5kZXggaWR4IG9uIHQgdXNpbmcgYnJpbiAoYSBpbnQ0X2Jsb29tX29wcyk7
CmRyb3AgaW5kZXggaWR4OwpFT0YKCgl0PWBncmVwIFRpbWUgYnJpbi50bXAgfCBoZWFkIC1u
IDEgfCBhd2sgJ3twcmludCAkMn0nYAoKCWVjaG8gcmFuZG9tLTEwMCBpbnQ0IGJyaW4tYmxv
b20gJHIgJHQKCmRvbmUKCnBzcWwgdGVzdCAtYyAiZHJvcCB0YWJsZSB0IiA+IC9kZXYvbnVs
bCAyPiYxCgoKIyByYW5kb20sIDEwMCB2YWx1ZXMsIGludDQsIHBhZGRlZAoKcHNxbCB0ZXN0
IC1jICJjcmVhdGUgdW5sb2dnZWQgdGFibGUgdCAoYSBpbnQsIGIgdGV4dCkiID4gL2Rldi9u
dWxsIDI+JjEKcHNxbCB0ZXN0IC1jICJpbnNlcnQgaW50byB0IHNlbGVjdCAxMDAgKiByYW5k
b20oKSwgbWQ1KGk6OnRleHQpIGZyb20gZ2VuZXJhdGVfc2VyaWVzKDEsJE5ST1dTKSBzKGkp
IiA+IC9kZXYvbnVsbCAyPiYxCnBzcWwgdGVzdCAtYyAidmFjdXVtIGFuYWx5emUgdCIgPiAv
ZGV2L251bGwgMj4mMQpwc3FsIHRlc3QgLWMgImNoZWNrcG9pbnQiID4gL2Rldi9udWxsIDI+
JjEKCmZvciByIGluIGBzZXEgMSAxMGA7IGRvCgoJIyByZWd1bGFyIGJ0cmVlIGluZGV4Cglw
c3FsIHRlc3QgPiBicmluLnRtcCA8PEVPRgpcdGltaW5nCmNyZWF0ZSBpbmRleCBpZHggb24g
dCAoYSk7CmRyb3AgaW5kZXggaWR4OwpFT0YKCgl0PWBncmVwIFRpbWUgYnJpbi50bXAgfCBo
ZWFkIC1uIDEgfCBhd2sgJ3twcmludCAkMn0nYAoKCWVjaG8gcmFuZG9tLTEwMCBpbnQ0LXBh
ZGRlZCBidHJlZSAkciAkdAoKCSMgYnJpbiBtaW5tYXggaW5kZXgKCXBzcWwgdGVzdCA+IGJy
aW4udG1wIDw8RU9GClx0aW1pbmcKY3JlYXRlIGluZGV4IGlkeCBvbiB0IHVzaW5nIGJyaW4g
KGEpOwpkcm9wIGluZGV4IGlkeDsKRU9GCgoJdD1gZ3JlcCBUaW1lIGJyaW4udG1wIHwgaGVh
ZCAtbiAxIHwgYXdrICd7cHJpbnQgJDJ9J2AKCgllY2hvIHJhbmRvbS0xMDAgaW50NC1wYWRk
ZWQgYnJpbi1taW5tYXggJHIgJHQKCgkjIGJyaW4gbXVsdGkgbWlubWF4IGluZGV4Cglwc3Fs
IHRlc3QgPiBicmluLnRtcCA8PEVPRgpcdGltaW5nCmNyZWF0ZSBpbmRleCBpZHggb24gdCB1
c2luZyBicmluIChhIGludDRfbWlubWF4X211bHRpX29wcyk7CmRyb3AgaW5kZXggaWR4OwpF
T0YKCgl0PWBncmVwIFRpbWUgYnJpbi50bXAgfCBoZWFkIC1uIDEgfCBhd2sgJ3twcmludCAk
Mn0nYAoKCWVjaG8gcmFuZG9tLTEwMCBpbnQ0LXBhZGRlZCBicmluLW11bHRpLW1pbm1heCAk
ciAkdAoKCSMgYnJpbiBibG9vbSBpbmRleAoJcHNxbCB0ZXN0ID4gYnJpbi50bXAgPDxFT0YK
XHRpbWluZwpjcmVhdGUgaW5kZXggaWR4IG9uIHQgdXNpbmcgYnJpbiAoYSBpbnQ0X2Jsb29t
X29wcyk7CmRyb3AgaW5kZXggaWR4OwpFT0YKCgl0PWBncmVwIFRpbWUgYnJpbi50bXAgfCBo
ZWFkIC1uIDEgfCBhd2sgJ3twcmludCAkMn0nYAoKCWVjaG8gcmFuZG9tLTEwMCBpbnQ0LXBh
ZGRlZCBicmluLWJsb29tICRyICR0Cgpkb25lCgpwc3FsIHRlc3QgLWMgImRyb3AgdGFibGUg
dCIgPiAvZGV2L251bGwgMj4mMQoKIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj
IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjCgojIHJhbmRvbSwgMTAw
MDAgZGlzdGluY3QgdmFsdWVzLCBpbnQ0Cgpwc3FsIHRlc3QgLWMgImNyZWF0ZSB1bmxvZ2dl
ZCB0YWJsZSB0IChhIGludCkiID4gL2Rldi9udWxsIDI+JjEKcHNxbCB0ZXN0IC1jICJpbnNl
cnQgaW50byB0IHNlbGVjdCAxMDAwMCAqIHJhbmRvbSgpIGZyb20gZ2VuZXJhdGVfc2VyaWVz
KDEsJE5ST1dTKSBzKGkpIiA+IC9kZXYvbnVsbCAyPiYxCnBzcWwgdGVzdCAtYyAidmFjdXVt
IGFuYWx5emUgdCIgPiAvZGV2L251bGwgMj4mMQpwc3FsIHRlc3QgLWMgImNoZWNrcG9pbnQi
ID4gL2Rldi9udWxsIDI+JjEKCmZvciByIGluIGBzZXEgMSAxMGA7IGRvCgoJIyByZWd1bGFy
IGJ0cmVlIGluZGV4Cglwc3FsIHRlc3QgPiBicmluLnRtcCA8PEVPRgpcdGltaW5nCmNyZWF0
ZSBpbmRleCBpZHggb24gdCAoYSk7CmRyb3AgaW5kZXggaWR4OwpFT0YKCgl0PWBncmVwIFRp
bWUgYnJpbi50bXAgfCBoZWFkIC1uIDEgfCBhd2sgJ3twcmludCAkMn0nYAoKCWVjaG8gcmFu
ZG9tLTEwMDAwIGludDQgYnRyZWUgJHIgJHQKCgkjIGJyaW4gbWlubWF4IGluZGV4Cglwc3Fs
IHRlc3QgPiBicmluLnRtcCA8PEVPRgpcdGltaW5nCmNyZWF0ZSBpbmRleCBpZHggb24gdCB1
c2luZyBicmluIChhKTsKZHJvcCBpbmRleCBpZHg7CkVPRgoKCXQ9YGdyZXAgVGltZSBicmlu
LnRtcCB8IGhlYWQgLW4gMSB8IGF3ayAne3ByaW50ICQyfSdgCgoJZWNobyByYW5kb20tMTAw
MDAgaW50NCBicmluLW1pbm1heCAkciAkdAoKCSMgYnJpbiBtdWx0aSBtaW5tYXggaW5kZXgK
CXBzcWwgdGVzdCA+IGJyaW4udG1wIDw8RU9GClx0aW1pbmcKY3JlYXRlIGluZGV4IGlkeCBv
biB0IHVzaW5nIGJyaW4gKGEgaW50NF9taW5tYXhfbXVsdGlfb3BzKTsKZHJvcCBpbmRleCBp
ZHg7CkVPRgoKCXQ9YGdyZXAgVGltZSBicmluLnRtcCB8IGhlYWQgLW4gMSB8IGF3ayAne3By
aW50ICQyfSdgCgoJZWNobyByYW5kb20tMTAwMDAgaW50NCBicmluLW11bHRpLW1pbm1heCAk
ciAkdAoKCSMgYnJpbiBibG9vbSBpbmRleAoJcHNxbCB0ZXN0ID4gYnJpbi50bXAgPDxFT0YK
XHRpbWluZwpjcmVhdGUgaW5kZXggaWR4IG9uIHQgdXNpbmcgYnJpbiAoYSBpbnQ0X2Jsb29t
X29wcyk7CmRyb3AgaW5kZXggaWR4OwpFT0YKCgl0PWBncmVwIFRpbWUgYnJpbi50bXAgfCBo
ZWFkIC1uIDEgfCBhd2sgJ3twcmludCAkMn0nYAoKCWVjaG8gcmFuZG9tLTEwMDAwIGludDQg
YnJpbi1ibG9vbSAkciAkdAoKZG9uZQoKcHNxbCB0ZXN0IC1jICJkcm9wIHRhYmxlIHQiID4g
L2Rldi9udWxsIDI+JjEKCgojIHJhbmRvbSwgMTAwMDAgdmFsdWVzLCBpbnQ0LCBwYWRkZWQK
CnBzcWwgdGVzdCAtYyAiY3JlYXRlIHVubG9nZ2VkIHRhYmxlIHQgKGEgaW50LCBiIHRleHQp
IiA+IC9kZXYvbnVsbCAyPiYxCnBzcWwgdGVzdCAtYyAiaW5zZXJ0IGludG8gdCBzZWxlY3Qg
MTAwMDAgKiByYW5kb20oKSwgbWQ1KGk6OnRleHQpIGZyb20gZ2VuZXJhdGVfc2VyaWVzKDEs
JE5ST1dTKSBzKGkpIiA+IC9kZXYvbnVsbCAyPiYxCnBzcWwgdGVzdCAtYyAidmFjdXVtIGFu
YWx5emUgdCIgPiAvZGV2L251bGwgMj4mMQpwc3FsIHRlc3QgLWMgImNoZWNrcG9pbnQiID4g
L2Rldi9udWxsIDI+JjEKCmZvciByIGluIGBzZXEgMSAxMGA7IGRvCgoJIyByZWd1bGFyIGJ0
cmVlIGluZGV4Cglwc3FsIHRlc3QgPiBicmluLnRtcCA8PEVPRgpcdGltaW5nCmNyZWF0ZSBp
bmRleCBpZHggb24gdCAoYSk7CmRyb3AgaW5kZXggaWR4OwpFT0YKCgl0PWBncmVwIFRpbWUg
YnJpbi50bXAgfCBoZWFkIC1uIDEgfCBhd2sgJ3twcmludCAkMn0nYAoKCWVjaG8gcmFuZG9t
LTEwMDAwIGludDQtcGFkZGVkIGJ0cmVlICRyICR0CgoJIyBicmluIG1pbm1heCBpbmRleAoJ
cHNxbCB0ZXN0ID4gYnJpbi50bXAgPDxFT0YKXHRpbWluZwpjcmVhdGUgaW5kZXggaWR4IG9u
IHQgdXNpbmcgYnJpbiAoYSk7CmRyb3AgaW5kZXggaWR4OwpFT0YKCgl0PWBncmVwIFRpbWUg
YnJpbi50bXAgfCBoZWFkIC1uIDEgfCBhd2sgJ3twcmludCAkMn0nYAoKCWVjaG8gcmFuZG9t
LTEwMDAwIGludDQtcGFkZGVkIGJyaW4tbWlubWF4ICRyICR0CgoJIyBicmluIG11bHRpIG1p
bm1heCBpbmRleAoJcHNxbCB0ZXN0ID4gYnJpbi50bXAgPDxFT0YKXHRpbWluZwpjcmVhdGUg
aW5kZXggaWR4IG9uIHQgdXNpbmcgYnJpbiAoYSBpbnQ0X21pbm1heF9tdWx0aV9vcHMpOwpk
cm9wIGluZGV4IGlkeDsKRU9GCgoJdD1gZ3JlcCBUaW1lIGJyaW4udG1wIHwgaGVhZCAtbiAx
IHwgYXdrICd7cHJpbnQgJDJ9J2AKCgllY2hvIHJhbmRvbS0xMDAwMCBpbnQ0LXBhZGRlZCBi
cmluLW11bHRpLW1pbm1heCAkciAkdAoKCSMgYnJpbiBibG9vbSBpbmRleAoJcHNxbCB0ZXN0
ID4gYnJpbi50bXAgPDxFT0YKXHRpbWluZwpjcmVhdGUgaW5kZXggaWR4IG9uIHQgdXNpbmcg
YnJpbiAoYSBpbnQ0X2Jsb29tX29wcyk7CmRyb3AgaW5kZXggaWR4OwpFT0YKCgl0PWBncmVw
IFRpbWUgYnJpbi50bXAgfCBoZWFkIC1uIDEgfCBhd2sgJ3twcmludCAkMn0nYAoKCWVjaG8g
cmFuZG9tLTEwMDAwIGludDQtcGFkZGVkIGJyaW4tYmxvb20gJHIgJHQKCmRvbmUKCnBzcWwg
dGVzdCAtYyAiZHJvcCB0YWJsZSB0IiA+IC9kZXYvbnVsbCAyPiYxCgo=
--------------FA974B75A0C3E9CA18CE7207--





view thread (21+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected]
  Subject: Re: [PATCH 8/8] batch build
  In-Reply-To: <no-message-id-1877536@localhost>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox